xref: /plan9/sys/src/cmd/vi/mem.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
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