/[gxemul]/trunk/src/memory_rw.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/memory_rw.c

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

revision 14 by dpavlin, Mon Oct 8 16:18:51 2007 UTC revision 40 by dpavlin, Mon Oct 8 16:22:11 2007 UTC
# Line 1  Line 1 
1  /*  /*
2   *  Copyright (C) 2003-2005  Anders Gavare.  All rights reserved.   *  Copyright (C) 2003-2007  Anders Gavare.  All rights reserved.
3   *   *
4   *  Redistribution and use in source and binary forms, with or without   *  Redistribution and use in source and binary forms, with or without
5   *  modification, are permitted provided that the following conditions are met:   *  modification, are permitted provided that the following conditions are met:
# Line 25  Line 25 
25   *  SUCH DAMAGE.   *  SUCH DAMAGE.
26   *   *
27   *   *
28   *  $Id: memory_rw.c,v 1.64 2005/09/22 09:06:59 debug Exp $   *  $Id: memory_rw.c,v 1.102 2007/04/16 15:13:44 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   *   *
# Line 48  Line 48 
48   *                      a placeholder for data when reading from memory   *                      a placeholder for data when reading from memory
49   *      len             the length of the 'data' buffer   *      len             the length of the 'data' buffer
50   *      writeflag       set to MEM_READ or MEM_WRITE   *      writeflag       set to MEM_READ or MEM_WRITE
51   *      cache_flags     CACHE_{NONE,DATA,INSTRUCTION} | other flags   *      misc_flags      CACHE_{NONE,DATA,INSTRUCTION} | other flags
52   *   *
53   *  If the address indicates access to a memory mapped device, that device'   *  If the address indicates access to a memory mapped device, that device'
54   *  read/write access function is called.   *  read/write access function is called.
55   *   *
  *  If instruction latency/delay support is enabled, then  
  *  cpu->instruction_delay is increased by the number of instruction to  
  *  delay execution.  
  *  
56   *  This function should not be called with cpu == NULL.   *  This function should not be called with cpu == NULL.
57   *   *
58   *  Returns one of the following:   *  Returns one of the following:
# Line 66  Line 62 
62   *  (MEMORY_ACCESS_FAILED is 0.)   *  (MEMORY_ACCESS_FAILED is 0.)
63   */   */
64  int MEMORY_RW(struct cpu *cpu, struct memory *mem, uint64_t vaddr,  int MEMORY_RW(struct cpu *cpu, struct memory *mem, uint64_t vaddr,
65          unsigned char *data, size_t len, int writeflag, int cache_flags)          unsigned char *data, size_t len, int writeflag, int misc_flags)
66  {  {
67  #ifdef MEM_ALPHA  #ifdef MEM_ALPHA
68          const int offset_mask = 0x1fff;          const int offset_mask = 0x1fff;
# Line 80  int MEMORY_RW(struct cpu *cpu, struct me Line 76  int MEMORY_RW(struct cpu *cpu, struct me
76          uint64_t paddr;          uint64_t paddr;
77          int cache, no_exceptions, offset;          int cache, no_exceptions, offset;
78          unsigned char *memblock;          unsigned char *memblock;
79  #ifdef MEM_MIPS          int dyntrans_device_danger = 0;
         int bintrans_cached = cpu->machine->bintrans_enable;  
 #endif  
         int bintrans_device_danger = 0;  
80    
81          no_exceptions = cache_flags & NO_EXCEPTIONS;          no_exceptions = misc_flags & NO_EXCEPTIONS;
82          cache = cache_flags & CACHE_FLAGS_MASK;          cache = misc_flags & CACHE_FLAGS_MASK;
83    
 #ifdef MEM_X86  
         /*  Real-mode wrap-around:  */  
         if (REAL_MODE && !(cache_flags & PHYSICAL)) {  
                 if ((vaddr & 0xffff) + len > 0x10000) {  
                         /*  Do one byte at a time:  */  
                         int res = 0, i;  
                         for (i=0; i<len; i++)  
                                 res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,  
                                     writeflag, cache_flags);  
                         return res;  
                 }  
         }  
   
         /*  Crossing a page boundary? Then do one byte at a time:  */  
         if ((vaddr & 0xfff) + len > 0x1000 && !(cache_flags & PHYSICAL)  
             && cpu->cd.x86.cr[0] & X86_CR0_PG) {  
                 /*  For WRITES: Read ALL BYTES FIRST and write them back!!!  
                     Then do a write of all the new bytes. This is to make sure  
                     than both pages around the boundary are writable so we don't  
                     do a partial write.  */  
                 int res = 0, i;  
                 if (writeflag == MEM_WRITE) {  
                         unsigned char tmp;  
                         for (i=0; i<len; i++) {  
                                 res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,  
                                     MEM_READ, cache_flags);  
                                 if (!res)  
                                         return 0;  
                                 res = MEMORY_RW(cpu, mem, vaddr+i, &tmp, 1,  
                                     MEM_WRITE, cache_flags);  
                                 if (!res)  
                                         return 0;  
                         }  
                         for (i=0; i<len; i++) {  
                                 res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,  
                                     MEM_WRITE, cache_flags);  
                                 if (!res)  
                                         return 0;  
                         }  
                 } else {  
                         for (i=0; i<len; i++) {  
                                 /*  Do one byte at a time:  */  
                                 res = MEMORY_RW(cpu, mem, vaddr+i, &data[i], 1,  
                                     writeflag, cache_flags);  
                                 if (!res) {  
                                         if (cache == CACHE_INSTRUCTION) {  
                                                 fatal("FAILED instruction "  
                                                     "fetch across page boundar"  
                                                     "y: todo. vaddr=0x%08x\n",  
                                                     (int)vaddr);  
                                                 cpu->running = 0;  
                                         }  
                                         return 0;  
                                 }  
                         }  
                 }  
                 return res;  
         }  
 #endif  /*  X86  */  
   
 #ifdef MEM_MIPS  
         if (bintrans_cached) {  
                 if (cache == CACHE_INSTRUCTION) {  
                         cpu->cd.mips.pc_bintrans_host_4kpage = NULL;  
                         cpu->cd.mips.pc_bintrans_paddr_valid = 0;  
                 }  
         }  
 #endif  /*  MEM_MIPS  */  
84    
85  #ifdef MEM_USERLAND  #ifdef MEM_USERLAND
86  #ifdef MEM_ALPHA  #ifdef MEM_ALPHA
# Line 163  int MEMORY_RW(struct cpu *cpu, struct me Line 88  int MEMORY_RW(struct cpu *cpu, struct me
88  #else  #else
89          paddr = vaddr & 0x7fffffff;          paddr = vaddr & 0x7fffffff;
90  #endif  #endif
91          goto have_paddr;  #else   /*  !MEM_USERLAND  */
92  #endif          if (misc_flags & PHYSICAL || cpu->translate_v2p == NULL) {
   
 #ifndef MEM_USERLAND  
 #ifdef MEM_MIPS  
         /*  
          *  For instruction fetch, are we on the same page as the last  
          *  instruction we fetched?  
          *  
          *  NOTE: There's no need to check this stuff here if this address  
          *  is known to be in host ram, as it's done at instruction fetch  
          *  time in cpu.c!  Only check if _host_4k_page == NULL.  
          */  
         if (cache == CACHE_INSTRUCTION &&  
             cpu->cd.mips.pc_last_host_4k_page == NULL &&  
             (vaddr & ~0xfff) == cpu->cd.mips.pc_last_virtual_page) {  
                 paddr = cpu->cd.mips.pc_last_physical_page | (vaddr & 0xfff);  
                 goto have_paddr;  
         }  
 #endif  /*  MEM_MIPS  */  
   
         if (cache_flags & PHYSICAL || cpu->translate_address == NULL) {  
93                  paddr = vaddr;                  paddr = vaddr;
   
 #ifdef MEM_ALPHA  
                 /*  paddr &= 0x1fffffff;  For testalpha  */  
                 paddr &= 0x000003ffffffffffULL;  
 #endif  
   
 #ifdef MEM_IA64  
                 /*  For testia64  */  
                 paddr &= 0x3fffffff;  
 #endif  
   
 #ifdef MEM_PPC  
                 if (cpu->cd.ppc.bits == 32)  
                         paddr &= 0xffffffff;  
 #endif  
   
 #ifdef MEM_SH  
                 paddr &= 0xffffffff;  
 #endif  
94          } else {          } else {
95                  ok = cpu->translate_address(cpu, vaddr, &paddr,                  ok = cpu->translate_v2p(cpu, vaddr, &paddr,
96                      (writeflag? FLAG_WRITEFLAG : 0) +                      (writeflag? FLAG_WRITEFLAG : 0) +
97                      (no_exceptions? FLAG_NOEXCEPTIONS : 0)                      (no_exceptions? FLAG_NOEXCEPTIONS : 0)
 #ifdef MEM_X86  
                     + (cache_flags & NO_SEGMENTATION)  
 #endif  
98  #ifdef MEM_ARM  #ifdef MEM_ARM
99                      + (cache_flags & MEMORY_USER_ACCESS)                      + (misc_flags & MEMORY_USER_ACCESS)
100  #endif  #endif
101                      + (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0));                      + (cache==CACHE_INSTRUCTION? FLAG_INSTR : 0));
102                  /*  If the translation caused an exception, or was invalid in  
103                      some way, we simply return without doing the memory                  /*
104                      access:  */                   *  If the translation caused an exception, or was invalid in
105                     *  some way, then simply return without doing the memory
106                     *  access:
107                     */
108                  if (!ok)                  if (!ok)
109                          return MEMORY_ACCESS_FAILED;                          return MEMORY_ACCESS_FAILED;
110          }          }
111    
112    #endif  /*  !MEM_USERLAND  */
 #ifdef MEM_X86  
         /*  DOS debugging :-)  */  
         if (!quiet_mode && !(cache_flags & PHYSICAL)) {  
                 if (paddr >= 0x400 && paddr <= 0x4ff)  
                         debug("{ PC BIOS DATA AREA: %s 0x%x }\n", writeflag ==  
                             MEM_WRITE? "writing to" : "reading from",  
                             (int)paddr);  
 #if 0  
                 if (paddr >= 0xf0000 && paddr <= 0xfffff)  
                         debug("{ BIOS ACCESS: %s 0x%x }\n",  
                             writeflag == MEM_WRITE? "writing to" :  
                             "reading from", (int)paddr);  
 #endif  
         }  
 #endif  
   
 #ifdef MEM_MIPS  
         /*  
          *  If correct cache emulation is enabled, and we need to simluate  
          *  cache misses even from the instruction cache, we can't run directly  
          *  from a host page. :-/  
          */  
 #if defined(ENABLE_CACHE_EMULATION) && defined(ENABLE_INSTRUCTION_DELAYS)  
 #else  
         if (cache == CACHE_INSTRUCTION) {  
                 cpu->cd.mips.pc_last_virtual_page = vaddr & ~0xfff;  
                 cpu->cd.mips.pc_last_physical_page = paddr & ~0xfff;  
                 cpu->cd.mips.pc_last_host_4k_page = NULL;  
   
                 /*  _last_host_4k_page will be set to 1 further down,  
                     if the page is actually in host ram  */  
         }  
 #endif  
 #endif  /*  MEM_MIPS  */  
 #endif  /*  ifndef MEM_USERLAND  */  
   
   
 #if defined(MEM_MIPS) || defined(MEM_USERLAND)  
 have_paddr:  
 #endif  
   
   
 #ifdef MEM_MIPS  
         /*  TODO: How about bintrans vs cache emulation?  */  
         if (bintrans_cached) {  
                 if (cache == CACHE_INSTRUCTION) {  
                         cpu->cd.mips.pc_bintrans_paddr_valid = 1;  
                         cpu->cd.mips.pc_bintrans_paddr = paddr;  
                 }  
         }  
 #endif  /*  MEM_MIPS  */  
   
113    
114    
115  #ifndef MEM_USERLAND  #ifndef MEM_USERLAND
116          /*          /*
117           *  Memory mapped device?           *  Memory mapped device?
118           *           *
119           *  TODO: this is utterly slow.           *  TODO: if paddr < base, but len enough, then the device should
120           *  TODO2: if paddr<base, but len enough, then we should write           *  still be written to!
          *  to a device to  
121           */           */
122          if (paddr >= mem->mmap_dev_minaddr && paddr < mem->mmap_dev_maxaddr) {          if (paddr >= mem->mmap_dev_minaddr && paddr < mem->mmap_dev_maxaddr) {
123                  uint64_t orig_paddr = paddr;                  uint64_t orig_paddr = paddr;
124                  int i, start, res;                  int i, start, end, res;
125    
126    #if 0
127    
128    TODO: The correct solution for this is to add RAM devices _around_ the
129    dangerous device. The solution below incurs a slowdown for _everything_,
130    not just the device in question.
131    
132                  /*                  /*
133                   *  Really really slow, but unfortunately necessary. This is                   *  Really really slow, but unfortunately necessary. This is
# Line 298  have_paddr: Line 137  have_paddr:
137                   *      b) offsets 0x124..0x777 are a device                   *      b) offsets 0x124..0x777 are a device
138                   *                   *
139                   *      1) a read is done from offset 0x100. the page is                   *      1) a read is done from offset 0x100. the page is
140                   *         added to the bintrans system as a "RAM" page                   *         added to the dyntrans system as a "RAM" page
141                   *      2) a bintranslated read is done from offset 0x200,                   *      2) a dyntranslated read is done from offset 0x200,
142                   *         which should access the device, but since the                   *         which should access the device, but since the
143                   *         entire page is added, it will access non-existant                   *         entire page is added, it will access non-existant
144                   *         RAM instead, without warning.                   *         RAM instead, without warning.
145                   *                   *
146                   *  Setting bintrans_device_danger = 1 on accesses which are                   *  Setting dyntrans_device_danger = 1 on accesses which are
147                   *  on _any_ offset on pages that are device mapped avoids                   *  on _any_ offset on pages that are device mapped avoids
148                   *  this problem, but it is probably not very fast.                   *  this problem, but it is probably not very fast.
149                     *
150                     *  TODO: Convert this into a quick (multi-level, 64-bit)
151                     *  address space lookup, to find dangerous pages.
152                   */                   */
153                  for (i=0; i<mem->n_mmapped_devices; i++)                  for (i=0; i<mem->n_mmapped_devices; i++)
154                          if (paddr >= (mem->dev_baseaddr[i] & ~offset_mask) &&                          if (paddr >= (mem->devices[i].baseaddr & ~offset_mask)&&
155                              paddr <= ((mem->dev_baseaddr[i] +                              paddr <= ((mem->devices[i].endaddr-1)|offset_mask)){
156                              mem->dev_length[i] - 1) | offset_mask)) {                                  dyntrans_device_danger = 1;
                                 bintrans_device_danger = 1;  
157                                  break;                                  break;
158                          }                          }
159    #endif
160    
161                  i = start = mem->last_accessed_device;                  start = 0; end = mem->n_mmapped_devices - 1;
162                    i = mem->last_accessed_device;
163    
164                  /*  Scan through all devices:  */                  /*  Scan through all devices:  */
165                  do {                  do {
166                          if (paddr >= mem->dev_baseaddr[i] &&                          if (paddr >= mem->devices[i].baseaddr &&
167                              paddr < mem->dev_baseaddr[i] + mem->dev_length[i]) {                              paddr < mem->devices[i].endaddr) {
168                                  /*  Found a device, let's access it:  */                                  /*  Found a device, let's access it:  */
169                                  mem->last_accessed_device = i;                                  mem->last_accessed_device = i;
170    
171                                  paddr -= mem->dev_baseaddr[i];                                  paddr -= mem->devices[i].baseaddr;
172                                  if (paddr + len > mem->dev_length[i])                                  if (paddr + len > mem->devices[i].length)
173                                          len = mem->dev_length[i] - paddr;                                          len = mem->devices[i].length - paddr;
174    
175                                  if (cpu->update_translation_table != NULL &&                                  if (cpu->update_translation_table != NULL &&
176                                      mem->dev_flags[i] & MEM_DYNTRANS_OK) {                                      !(ok & MEMORY_NOT_FULL_PAGE) &&
177                                        mem->devices[i].flags & DM_DYNTRANS_OK) {
178                                          int wf = writeflag == MEM_WRITE? 1 : 0;                                          int wf = writeflag == MEM_WRITE? 1 : 0;
179                                            unsigned char *host_addr;
180    
181                                          if (writeflag) {                                          if (!(mem->devices[i].flags &
182                                                  if (paddr < mem->                                              DM_DYNTRANS_WRITE_OK))
183                                                      dev_dyntrans_write_low[i])                                                  wf = 0;
184                                                          mem->  
185                                                          dev_dyntrans_write_low                                          if (writeflag && wf) {
186                                                              [i] = paddr &                                                  if (paddr < mem->devices[i].
187                                                              ~offset_mask;                                                      dyntrans_write_low)
188                                                  if (paddr >= mem->                                                          mem->devices[i].
189                                                      dev_dyntrans_write_high[i])                                                          dyntrans_write_low =
190                                                          mem->                                                              paddr &~offset_mask;
191                                                          dev_dyntrans_write_high                                                  if (paddr >= mem->devices[i].
192                                                              [i] = paddr |                                                      dyntrans_write_high)
193                                                              offset_mask;                                                          mem->devices[i].
194                                                            dyntrans_write_high =
195                                                                paddr | offset_mask;
196                                          }                                          }
197    
198                                          if (!(mem->dev_flags[i] &                                          if (mem->devices[i].flags &
199                                              MEM_DYNTRANS_WRITE_OK))                                              DM_EMULATED_RAM) {
200                                                  wf = 0;                                                  /*  MEM_WRITE to force the page
201                                                        to be allocated, if it
202                                                        wasn't already  */
203                                                    uint64_t *pp = (uint64_t *)mem->
204                                                        devices[i].dyntrans_data;
205                                                    uint64_t p = orig_paddr - *pp;
206                                                    host_addr =
207                                                        memory_paddr_to_hostaddr(
208                                                        mem, p & ~offset_mask,
209                                                        MEM_WRITE);
210                                            } else {
211                                                    host_addr = mem->devices[i].
212                                                        dyntrans_data +
213                                                        (paddr & ~offset_mask);
214                                            }
215    
216                                          cpu->update_translation_table(cpu,                                          cpu->update_translation_table(cpu,
217                                              vaddr & ~offset_mask,                                              vaddr & ~offset_mask, host_addr,
                                             mem->dev_dyntrans_data[i] +  
                                             (paddr & ~offset_mask),  
218                                              wf, orig_paddr & ~offset_mask);                                              wf, orig_paddr & ~offset_mask);
219                                  }                                  }
220    
221                                  res = 0;                                  res = 0;
222                                  if (!no_exceptions || (mem->dev_flags[i] &                                  if (!no_exceptions || (mem->devices[i].flags &
223                                      MEM_READING_HAS_NO_SIDE_EFFECTS))                                      DM_READS_HAVE_NO_SIDE_EFFECTS))
224                                          res = mem->dev_f[i](cpu, mem, paddr,                                          res = mem->devices[i].f(cpu, mem, paddr,
225                                              data, len, writeflag,                                              data, len, writeflag,
226                                              mem->dev_extra[i]);                                              mem->devices[i].extra);
227    
 #ifdef ENABLE_INSTRUCTION_DELAYS  
228                                  if (res == 0)                                  if (res == 0)
229                                          res = -1;                                          res = -1;
230    
                                 cpu->cd.mips.instruction_delay +=  
                                     ( (abs(res) - 1) *  
                                      cpu->cd.mips.cpu_type.instrs_per_cycle );  
 #endif  
   
 #ifndef MEM_X86  
231                                  /*                                  /*
232                                   *  If accessing the memory mapped device                                   *  If accessing the memory mapped device
233                                   *  failed, then return with a DBE exception.                                   *  failed, then return with a DBE exception.
# Line 384  have_paddr: Line 236  have_paddr:
236                                          debug("%s device '%s' addr %08lx "                                          debug("%s device '%s' addr %08lx "
237                                              "failed\n", writeflag?                                              "failed\n", writeflag?
238                                              "writing to" : "reading from",                                              "writing to" : "reading from",
239                                              mem->dev_name[i], (long)paddr);                                              mem->devices[i].name, (long)paddr);
240  #ifdef MEM_MIPS  #ifdef MEM_MIPS
241                                          mips_cpu_exception(cpu, EXCEPTION_DBE,                                          mips_cpu_exception(cpu, EXCEPTION_DBE,
242                                              0, vaddr, 0, 0, 0, 0);                                              0, vaddr, 0, 0, 0, 0);
243  #endif  #endif
244                                          return MEMORY_ACCESS_FAILED;                                          return MEMORY_ACCESS_FAILED;
245                                  }                                  }
 #endif  
246                                  goto do_return_ok;                                  goto do_return_ok;
247                          }                          }
248    
249                          i ++;                          if (paddr < mem->devices[i].baseaddr)
250                          if (i == mem->n_mmapped_devices)                                  end = i - 1;
251                                  i = 0;                          if (paddr >= mem->devices[i].endaddr)
252                  } while (i != start);                                  start = i + 1;
253                            i = (start + end) >> 1;
254                    } while (start <= end);
255          }          }
256    
257    
# Line 410  have_paddr: Line 263  have_paddr:
263          switch (cpu->cd.mips.cpu_type.mmu_model) {          switch (cpu->cd.mips.cpu_type.mmu_model) {
264          case MMU3K:          case MMU3K:
265                  /*  if not uncached addess  (TODO: generalize this)  */                  /*  if not uncached addess  (TODO: generalize this)  */
266                  if (!(cache_flags & PHYSICAL) && cache != CACHE_NONE &&                  if (!(misc_flags & PHYSICAL) && cache != CACHE_NONE &&
267                      !((vaddr & 0xffffffffULL) >= 0xa0000000ULL &&                      !((vaddr & 0xffffffffULL) >= 0xa0000000ULL &&
268                        (vaddr & 0xffffffffULL) <= 0xbfffffffULL)) {                        (vaddr & 0xffffffffULL) <= 0xbfffffffULL)) {
269                          if (memory_cache_R3000(cpu, cache, paddr,                          if (memory_cache_R3000(cpu, cache, paddr,
# Line 440  have_paddr: Line 293  have_paddr:
293                  } else                  } else
294  #endif /* MIPS */  #endif /* MIPS */
295                  {                  {
296                          if (paddr >= mem->physical_max) {                          if (paddr >= mem->physical_max && !no_exceptions)
297                                  char *symbol;                                  memory_warn_about_unimplemented_addr
298                                  uint64_t old_pc;                                      (cpu, mem, writeflag, paddr, data, len);
                                 uint64_t offset;  
   
 #ifdef MEM_MIPS  
                                 old_pc = cpu->cd.mips.pc_last;  
 #else  
                                 /*  Default instruction size on most  
                                     RISC archs is 32 bits:  */  
                                 old_pc = cpu->pc - sizeof(uint32_t);  
 #endif  
   
                                 /*  This allows for example OS kernels to probe  
                                     memory a few KBs past the end of memory,  
                                     without giving too many warnings.  */  
                                 if (!quiet_mode && !no_exceptions && paddr >=  
                                     mem->physical_max + 0x40000) {  
                                         fatal("[ memory_rw(): writeflag=%i ",  
                                             writeflag);  
                                         if (writeflag) {  
                                                 unsigned int i;  
                                                 debug("data={", writeflag);  
                                                 if (len > 16) {  
                                                         int start2 = len-16;  
                                                         for (i=0; i<16; i++)  
                                                                 debug("%s%02x",  
                                                                     i?",":"",  
                                                                     data[i]);  
                                                         debug(" .. ");  
                                                         if (start2 < 16)  
                                                                 start2 = 16;  
                                                         for (i=start2; i<len;  
                                                             i++)  
                                                                 debug("%s%02x",  
                                                                     i?",":"",  
                                                                     data[i]);  
                                                 } else  
                                                         for (i=0; i<len; i++)  
                                                                 debug("%s%02x",  
                                                                     i?",":"",  
                                                                     data[i]);  
                                                 debug("}");  
                                         }  
   
                                         fatal(" paddr=0x%llx >= physical_max"  
                                             "; pc=", (long long)paddr);  
                                         if (cpu->is_32bit)  
                                                 fatal("0x%08x",(int)old_pc);  
                                         else  
                                                 fatal("0x%016llx",  
                                                     (long long)old_pc);  
                                         symbol = get_symbol_name(  
                                             &cpu->machine->symbol_context,  
                                             old_pc, &offset);  
                                         fatal(" <%s> ]\n",  
                                             symbol? symbol : " no symbol ");  
                                 }  
   
                                 if (cpu->machine->single_step_on_bad_addr) {  
                                         fatal("[ unimplemented access to "  
                                             "0x%llx, pc=0x",(long long)paddr);  
                                         if (cpu->is_32bit)  
                                                 fatal("%08x ]\n",  
                                                     (int)old_pc);  
                                         else  
                                                 fatal("%016llx ]\n",  
                                                     (long long)old_pc);  
                                         single_step = 1;  
                                 }  
                         }  
299    
300                          if (writeflag == MEM_READ) {                          if (writeflag == MEM_READ) {
 #ifdef MEM_X86  
                                 /*  Reading non-existant memory on x86:  */  
                                 memset(data, 0xff, len);  
 #else  
301                                  /*  Return all zeroes? (Or 0xff? TODO)  */                                  /*  Return all zeroes? (Or 0xff? TODO)  */
302                                  memset(data, 0, len);                                  memset(data, 0, len);
 #endif  
303    
304  #ifdef MEM_MIPS  #ifdef MEM_MIPS
305                                  /*                                  /*
# Line 550  have_paddr: Line 330  have_paddr:
330    
331          /*          /*
332           *  Uncached access:           *  Uncached access:
333             *
334             *  1)  Translate the physical address to a host address.
335             *
336             *  2)  Insert this virtual->physical->host translation into the
337             *      fast translation arrays (using update_translation_table()).
338             *
339             *  3)  If this was a Write, then invalidate any code translations
340             *      in that page.
341           */           */
342          memblock = memory_paddr_to_hostaddr(mem, paddr, writeflag);          memblock = memory_paddr_to_hostaddr(mem, paddr & ~offset_mask,
343                writeflag);
344          if (memblock == NULL) {          if (memblock == NULL) {
345                  if (writeflag == MEM_READ)                  if (writeflag == MEM_READ)
346                          memset(data, 0, len);                          memset(data, 0, len);
347                  goto do_return_ok;                  goto do_return_ok;
348          }          }
349    
350          offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1);          offset = paddr & offset_mask;
351    
352          if (cpu->update_translation_table != NULL && !bintrans_device_danger)          if (cpu->update_translation_table != NULL && !dyntrans_device_danger
353    #ifdef MEM_MIPS
354                /*  Ugly hack for R2000/R3000 caches:  */
355                && (cpu->cd.mips.cpu_type.mmu_model != MMU3K ||
356                !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & MIPS1_ISOL_CACHES))
357    #endif
358    #ifndef MEM_MIPS
359    /*          && !(misc_flags & MEMORY_USER_ACCESS)  */
360    #ifndef MEM_USERLAND
361                && !(ok & MEMORY_NOT_FULL_PAGE)
362    #endif
363    #endif
364                && !no_exceptions)
365                  cpu->update_translation_table(cpu, vaddr & ~offset_mask,                  cpu->update_translation_table(cpu, vaddr & ~offset_mask,
366                      memblock + (offset & ~offset_mask),                      memblock, (misc_flags & MEMORY_USER_ACCESS) |
367  #if 0  #if !defined(MEM_MIPS) && !defined(MEM_USERLAND)
368                      cache == CACHE_INSTRUCTION?                      (cache == CACHE_INSTRUCTION?
369                          (writeflag == MEM_WRITE? 1 : 0)                          (writeflag == MEM_WRITE? 1 : 0) : ok - 1),
                         : ok - 1,  
370  #else  #else
371                      writeflag == MEM_WRITE? 1 : 0,                      (writeflag == MEM_WRITE? 1 : 0),
372  #endif  #endif
373                      paddr & ~offset_mask);                      paddr & ~offset_mask);
374    
375          if (writeflag == MEM_WRITE &&          /*
376              cpu->invalidate_code_translation != NULL)           *  If writing, or if mapping a page where writing is ok later on,
377             *  then invalidate code translations for the (physical) page address:
378             */
379            if ((writeflag == MEM_WRITE
380    #if !defined(MEM_USERLAND)
381                || ok == 2
382    #endif
383                ) && cpu->invalidate_code_translation != NULL)
384                  cpu->invalidate_code_translation(cpu, paddr, INVALIDATE_PADDR);                  cpu->invalidate_code_translation(cpu, paddr, INVALIDATE_PADDR);
385    
386          if (writeflag == MEM_WRITE) {          if ((paddr&((1<<BITS_PER_MEMBLOCK)-1)) + len > (1<<BITS_PER_MEMBLOCK)) {
387                  /*  Ugly optimization, but it works:  */                  printf("Write over memblock boundary?\n");
388                  if (len == sizeof(uint32_t) && (offset & 3)==0                  exit(1);
                     && ((size_t)data&3)==0)  
                         *(uint32_t *)(memblock + offset) = *(uint32_t *)data;  
                 else if (len == sizeof(uint8_t))  
                         *(uint8_t *)(memblock + offset) = *(uint8_t *)data;  
                 else  
                         memcpy(memblock + offset, data, len);  
         } else {  
                 /*  Ugly optimization, but it works:  */  
                 if (len == sizeof(uint32_t) && (offset & 3)==0  
                     && ((size_t)data&3)==0)  
                         *(uint32_t *)data = *(uint32_t *)(memblock + offset);  
                 else if (len == sizeof(uint8_t))  
                         *(uint8_t *)data = *(uint8_t *)(memblock + offset);  
                 else  
                         memcpy(data, memblock + offset, len);  
   
 #ifdef MEM_MIPS  
                 if (cache == CACHE_INSTRUCTION) {  
                         cpu->cd.mips.pc_last_host_4k_page = memblock  
                             + (offset & ~offset_mask);  
                         if (bintrans_cached) {  
                                 cpu->cd.mips.pc_bintrans_host_4kpage =  
                                     cpu->cd.mips.pc_last_host_4k_page;  
                         }  
                 }  
 #endif  /*  MIPS  */  
389          }          }
390    
391            /*  And finally, read or write the data:  */
392            if (writeflag == MEM_WRITE)
393                    memcpy(memblock + offset, data, len);
394            else
395                    memcpy(data, memblock + offset, len);
396    
397  do_return_ok:  do_return_ok:
398          return MEMORY_ACCESS_OK;          return MEMORY_ACCESS_OK;

Legend:
Removed from v.14  
changed lines
  Added in v.40

  ViewVC Help
Powered by ViewVC 1.1.26