1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <mach.h>
5 #define Extern extern
6 #include "mips.h"
7
8 extern ulong textbase;
9
10 ulong
ifetch(ulong addr)11 ifetch(ulong addr)
12 {
13 uchar *va;
14
15 if(addr&3) {
16 Bprint(bioout, "Address error (I-fetch) vaddr %.8lux\n", addr);
17 longjmp(errjmp, 0);
18 }
19
20 if(icache.on)
21 updateicache(addr);
22
23 iprof[(addr-textbase)/PROFGRAN]++;
24
25 va = vaddr(addr);
26 va += addr&(BY2PG-1);
27
28 return va[0]<<24 | va[1]<<16 | va[2]<<8 | va[3];
29 }
30
31 ulong
getmem_4(ulong addr)32 getmem_4(ulong addr)
33 {
34 ulong val;
35 int i;
36
37 val = 0;
38 for(i = 0; i < 4; i++)
39 val = val<<8 | getmem_b(addr++);
40 return val;
41 }
42
43 ulong
getmem_2(ulong addr)44 getmem_2(ulong addr)
45 {
46 ulong val;
47
48 val = getmem_b(addr);
49 val = val<<8 | getmem_b(addr+1);
50
51 return val;
52 }
53
54 ulong
getmem_w(ulong addr)55 getmem_w(ulong addr)
56 {
57 uchar *va;
58
59 if(addr&3) {
60 Bprint(bioout, "Address error (Load) vaddr %.8lux\n", addr);
61 longjmp(errjmp, 0);
62 }
63 if(membpt)
64 brkchk(addr, Read);
65
66 va = vaddr(addr);
67 va += addr&(BY2PG-1);
68
69 return va[0]<<24 | va[1]<<16 | va[2]<<8 | va[3];;
70 }
71
72 ushort
getmem_h(ulong addr)73 getmem_h(ulong addr)
74 {
75 uchar *va;
76
77 if(addr&1) {
78 Bprint(bioout, "Address error (Load) vaddr %.8lux\n", addr);
79 longjmp(errjmp, 0);
80 }
81 if(membpt)
82 brkchk(addr, Read);
83
84 va = vaddr(addr);
85 va += addr&(BY2PG-1);
86
87 return va[0]<<8 | va[1];
88 }
89
90 uchar
getmem_b(ulong addr)91 getmem_b(ulong addr)
92 {
93 uchar *va;
94
95 if(membpt)
96 brkchk(addr, Read);
97
98 va = vaddr(addr);
99 va += addr&(BY2PG-1);
100 return va[0];
101 }
102
103 void
putmem_w(ulong addr,ulong data)104 putmem_w(ulong addr, ulong data)
105 {
106 uchar *va;
107
108 if(addr&3) {
109 Bprint(bioout, "Address error (Store) vaddr %.8lux\n", addr);
110 longjmp(errjmp, 0);
111 }
112
113 va = vaddr(addr);
114 va += addr&(BY2PG-1);
115
116 va[0] = data>>24;
117 va[1] = data>>16;
118 va[2] = data>>8;
119 va[3] = data;
120 if(membpt)
121 brkchk(addr, Write);
122 }
123 void
putmem_b(ulong addr,uchar data)124 putmem_b(ulong addr, uchar data)
125 {
126 uchar *va;
127
128 va = vaddr(addr);
129 va += addr&(BY2PG-1);
130 va[0] = data;
131 if(membpt)
132 brkchk(addr, Write);
133 }
134
135 void
putmem_h(ulong addr,short data)136 putmem_h(ulong addr, short data)
137 {
138 uchar *va;
139
140 if(addr&1) {
141 Bprint(bioout, "Address error (Store) vaddr %.8lux\n", addr);
142 longjmp(errjmp, 0);
143 }
144
145 va = vaddr(addr);
146 va += addr&(BY2PG-1);
147 va[0] = data>>8;
148 va[1] = data;
149 if(membpt)
150 brkchk(addr, Write);
151 }
152
153 char *
memio(char * mb,ulong mem,int size,int dir)154 memio(char *mb, ulong mem, int size, int dir)
155 {
156 int i;
157 char *buf, c;
158
159 if(mb == 0)
160 mb = emalloc(size);
161
162 buf = mb;
163 switch(dir) {
164 default:
165 fatal(0, "memio");
166 case MemRead:
167 while(size--)
168 *mb++ = getmem_b(mem++);
169 break;
170 case MemReadstring:
171 for(;;) {
172 if(size-- == 0) {
173 Bprint(bioout, "memio: user/kernel copy too long for mipsim\n");
174 longjmp(errjmp, 0);
175 }
176 c = getmem_b(mem++);
177 *mb++ = c;
178 if(c == '\0')
179 break;
180 }
181 break;
182 case MemWrite:
183 for(i = 0; i < size; i++)
184 putmem_b(mem++, *mb++);
185 break;
186 }
187 return buf;
188 }
189
190 void
dotlb(ulong vaddr)191 dotlb(ulong vaddr)
192 {
193 ulong *l, *e;
194
195 vaddr &= ~(BY2PG-1);
196
197 e = &tlb.tlbent[tlb.tlbsize];
198 for(l = tlb.tlbent; l < e; l++)
199 if(*l == vaddr) {
200 tlb.hit++;
201 return;
202 }
203
204 tlb.miss++;
205 tlb.tlbent[lnrand(tlb.tlbsize)] = vaddr;
206 }
207
208 void*
vaddr1(ulong addr)209 vaddr1(ulong addr)
210 {
211 Segment *s, *es;
212 int off, foff, l, n;
213 uchar **p, *a;
214
215 if(tlb.on)
216 dotlb(addr);
217
218 es = &memory.seg[Nseg];
219 for(s = memory.seg; s < es; s++) {
220 if(addr >= s->base && addr < s->end) {
221 s->refs++;
222 off = (addr-s->base)/BY2PG;
223 p = &s->table[off];
224 if(*p)
225 return *p;
226 s->rss++;
227 switch(s->type) {
228 default:
229 fatal(0, "vaddr");
230 case Text:
231 *p = emalloc(BY2PG);
232 if(seek(text, s->fileoff+(off*BY2PG), 0) < 0)
233 fatal(1, "vaddr text seek");
234 if(read(text, *p, BY2PG) < 0)
235 fatal(1, "vaddr text read");
236 return *p;
237 case Data:
238 *p = emalloc(BY2PG);
239 foff = s->fileoff+(off*BY2PG);
240 if(seek(text, foff, 0) < 0)
241 fatal(1, "vaddr text seek");
242 n = read(text, *p, BY2PG);
243 if(n < 0)
244 fatal(1, "vaddr text read");
245 if(foff + n > s->fileend) {
246 l = BY2PG - (s->fileend-foff);
247 a = *p+(s->fileend-foff);
248 memset(a, 0, l);
249 }
250 return *p;
251 case Bss:
252 case Stack:
253 *p = emalloc(BY2PG);
254 return *p;
255 }
256 }
257 }
258 return 0;
259 }
260
261 void*
vaddr(ulong addr)262 vaddr(ulong addr)
263 {
264 void *v;
265
266 v = vaddr1(addr);
267 if(v == 0) {
268 Bprint(bioout, "User TLB miss vaddr 0x%.8lux\n", addr);
269 longjmp(errjmp, 0);
270 }
271 return v;
272 }
273
274 int
badvaddr(ulong addr,int n)275 badvaddr(ulong addr, int n)
276 {
277 void *v;
278
279 if(addr & (n-1))
280 return 1;
281 v = vaddr1(addr);
282 if(v == 0)
283 return 1;
284 return 0;
285 }
286