/[gxemul]/upstream/0.3.6/src/cpus/memory_fast_v2h.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

Contents of /upstream/0.3.6/src/cpus/memory_fast_v2h.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 15 - (show annotations)
Mon Oct 8 16:18:56 2007 UTC (16 years, 7 months ago) by dpavlin
File MIME type: text/plain
File size: 6909 byte(s)
0.3.6
1 /*
2 * Copyright (C) 2004-2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: memory_fast_v2h.c,v 1.1 2005/08/29 14:36:42 debug Exp $
29 *
30 * Fast virtual memory to host address, used by binary translated code.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35
36 #include "bintrans.h"
37 #include "cpu.h"
38 #include "memory.h"
39 #include "cpu_mips.h"
40 #include "misc.h"
41
42
43 #ifdef BINTRANS
44
45 /*
46 * fast_vaddr_to_hostaddr():
47 *
48 * Used by dynamically translated code. The caller should have made sure
49 * that the access is aligned correctly.
50 *
51 * Return value is a pointer to a host page + offset, if the page was
52 * writable (or writeflag was zero), if the virtual address was translatable
53 * to a paddr, and if the paddr was translatable to a host address.
54 *
55 * On error, NULL is returned. The caller (usually the dynamically
56 * generated machine code) must check for this.
57 */
58 unsigned char *fast_vaddr_to_hostaddr(struct cpu *cpu,
59 uint64_t vaddr, int writeflag)
60 {
61 int ok, i, n, start_and_stop;
62 uint64_t paddr, vaddr_page;
63 unsigned char *memblock;
64 size_t offset;
65 const int MAX = N_BINTRANS_VADDR_TO_HOST;
66
67 /* printf("fast_vaddr_to_hostaddr(): cpu=%p, vaddr=%016llx, wf=%i\n",
68 cpu, (long long)vaddr, writeflag); */
69
70 #if 0
71 /* Hm. This seems to work now, so this #if X can be removed. (?) */
72
73 /*
74 * TODO:
75 *
76 * Why doesn't this work yet?
77 */
78 if ((vaddr & 0xc0000000ULL) >= 0xc0000000ULL && writeflag) {
79 return NULL;
80 }
81 #endif
82
83
84 vaddr_page = vaddr & ~0xfff;
85 i = start_and_stop = cpu->cd.mips.bintrans_next_index;
86 n = 0;
87 for (;;) {
88 if (cpu->cd.mips.bintrans_data_vaddr[i] == vaddr_page &&
89 cpu->cd.mips.bintrans_data_hostpage[i] != NULL &&
90 cpu->cd.mips.bintrans_data_writable[i] >= writeflag) {
91 uint64_t tmpaddr;
92 unsigned char *tmpptr;
93 int tmpwf;
94
95 if (n < 3)
96 return cpu->cd.mips.bintrans_data_hostpage[i]
97 + (vaddr & 0xfff);
98
99 cpu->cd.mips.bintrans_next_index = start_and_stop - 1;
100 if (cpu->cd.mips.bintrans_next_index < 0)
101 cpu->cd.mips.bintrans_next_index = MAX - 1;
102
103 tmpptr = cpu->cd.mips.bintrans_data_hostpage[
104 cpu->cd.mips.bintrans_next_index];
105 tmpaddr = cpu->cd.mips.bintrans_data_vaddr[
106 cpu->cd.mips.bintrans_next_index];
107 tmpwf = cpu->cd.mips.bintrans_data_writable[
108 cpu->cd.mips.bintrans_next_index];
109
110 cpu->cd.mips.bintrans_data_hostpage[
111 cpu->cd.mips.bintrans_next_index] =
112 cpu->cd.mips.bintrans_data_hostpage[i];
113 cpu->cd.mips.bintrans_data_vaddr[
114 cpu->cd.mips.bintrans_next_index] =
115 cpu->cd.mips.bintrans_data_vaddr[i];
116 cpu->cd.mips.bintrans_data_writable[
117 cpu->cd.mips.bintrans_next_index] =
118 cpu->cd.mips.bintrans_data_writable[i];
119
120 cpu->cd.mips.bintrans_data_hostpage[i] = tmpptr;
121 cpu->cd.mips.bintrans_data_vaddr[i] = tmpaddr;
122 cpu->cd.mips.bintrans_data_writable[i] = tmpwf;
123
124 return cpu->cd.mips.bintrans_data_hostpage[
125 cpu->cd.mips.bintrans_next_index] + (vaddr & 0xfff);
126 }
127
128 n ++;
129 i ++;
130 if (i == MAX)
131 i = 0;
132 if (i == start_and_stop)
133 break;
134 }
135
136 ok = cpu->translate_address(cpu, vaddr, &paddr,
137 (writeflag? FLAG_WRITEFLAG : 0) + FLAG_NOEXCEPTIONS);
138 /* printf("ok=%i\n", ok); */
139 if (!ok)
140 return NULL;
141
142 for (i=0; i<cpu->mem->n_mmapped_devices; i++)
143 if (paddr >= (cpu->mem->dev_baseaddr[i] & ~0xfff) &&
144 paddr <= ((cpu->mem->dev_baseaddr[i] +
145 cpu->mem->dev_length[i] - 1) | 0xfff)) {
146 if (cpu->mem->dev_flags[i] & MEM_DYNTRANS_OK) {
147 paddr -= cpu->mem->dev_baseaddr[i];
148
149 /* Within a device _page_ but not within the
150 actual device? Then abort: */
151 if ((int64_t)paddr < 0 ||
152 paddr >= cpu->mem->dev_length[i])
153 return NULL;
154
155 if (writeflag) {
156 uint64_t low_paddr = paddr & ~0xfff;
157 uint64_t high_paddr = paddr | 0xfff;
158 if (!(cpu->mem->dev_flags[i] &
159 MEM_DYNTRANS_WRITE_OK))
160 return NULL;
161
162 if (low_paddr < cpu->mem->
163 dev_dyntrans_write_low[i])
164 cpu->mem->
165 dev_dyntrans_write_low[i] =
166 low_paddr;
167 if (high_paddr > cpu->mem->
168 dev_dyntrans_write_high[i])
169 cpu->mem->
170 dev_dyntrans_write_high[i]
171 = high_paddr;
172 }
173
174 cpu->cd.mips.bintrans_next_index --;
175 if (cpu->cd.mips.bintrans_next_index < 0)
176 cpu->cd.mips.bintrans_next_index =
177 MAX - 1;
178 cpu->cd.mips.bintrans_data_hostpage[cpu->
179 cd.mips.bintrans_next_index] = cpu->mem->
180 dev_dyntrans_data[i] + (paddr & ~0xfff);
181 cpu->cd.mips.bintrans_data_vaddr[cpu->
182 cd.mips.bintrans_next_index] = vaddr_page;
183 cpu->cd.mips.bintrans_data_writable[cpu->
184 cd.mips.bintrans_next_index] = writeflag;
185 return cpu->mem->dev_dyntrans_data[i] + paddr;
186 } else
187 return NULL;
188 }
189
190 memblock = memory_paddr_to_hostaddr(cpu->mem, paddr,
191 writeflag? MEM_WRITE : MEM_READ);
192 if (memblock == NULL)
193 return NULL;
194
195 offset = paddr & ((1 << BITS_PER_MEMBLOCK) - 1);
196
197 if (writeflag)
198 bintrans_invalidate(cpu, paddr);
199
200 cpu->cd.mips.bintrans_next_index --;
201 if (cpu->cd.mips.bintrans_next_index < 0)
202 cpu->cd.mips.bintrans_next_index = MAX - 1;
203 cpu->cd.mips.bintrans_data_hostpage[cpu->cd.mips.bintrans_next_index] =
204 memblock + (offset & ~0xfff);
205 cpu->cd.mips.bintrans_data_vaddr[cpu->cd.mips.bintrans_next_index] =
206 vaddr_page;
207 cpu->cd.mips.bintrans_data_writable[cpu->cd.mips.bintrans_next_index] =
208 writeflag; /* ok - 1; */
209
210 return memblock + offset;
211 }
212
213 #endif /* BINTRANS */

  ViewVC Help
Powered by ViewVC 1.1.26