xref: /plan9/sys/src/cmd/vi/mem.c (revision 7dd7cddf99dd7472612f1413b4da293630e6b1bc)
13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier #include <bio.h>
4bd389b36SDavid du Colombier #include <mach.h>
53e12c5d1SDavid du Colombier #define Extern extern
63e12c5d1SDavid du Colombier #include "mips.h"
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier extern ulong	textbase;
93e12c5d1SDavid du Colombier 
103e12c5d1SDavid du Colombier ulong
ifetch(ulong addr)113e12c5d1SDavid du Colombier ifetch(ulong addr)
123e12c5d1SDavid du Colombier {
133e12c5d1SDavid du Colombier 	uchar *va;
143e12c5d1SDavid du Colombier 
153e12c5d1SDavid du Colombier 	if(addr&3) {
163e12c5d1SDavid du Colombier 		Bprint(bioout, "Address error (I-fetch) vaddr %.8lux\n", addr);
173e12c5d1SDavid du Colombier 		longjmp(errjmp, 0);
183e12c5d1SDavid du Colombier 	}
193e12c5d1SDavid du Colombier 
203e12c5d1SDavid du Colombier 	if(icache.on)
213e12c5d1SDavid du Colombier 		updateicache(addr);
223e12c5d1SDavid du Colombier 
233e12c5d1SDavid du Colombier 	iprof[(addr-textbase)/PROFGRAN]++;
243e12c5d1SDavid du Colombier 
253e12c5d1SDavid du Colombier 	va = vaddr(addr);
263e12c5d1SDavid du Colombier 	va += addr&(BY2PG-1);
273e12c5d1SDavid du Colombier 
283e12c5d1SDavid du Colombier 	return va[0]<<24 | va[1]<<16 | va[2]<<8 | va[3];
293e12c5d1SDavid du Colombier }
303e12c5d1SDavid du Colombier 
313e12c5d1SDavid du Colombier ulong
getmem_4(ulong addr)323e12c5d1SDavid du Colombier getmem_4(ulong addr)
333e12c5d1SDavid du Colombier {
343e12c5d1SDavid du Colombier 	ulong val;
353e12c5d1SDavid du Colombier 	int i;
363e12c5d1SDavid du Colombier 
373e12c5d1SDavid du Colombier 	val = 0;
383e12c5d1SDavid du Colombier 	for(i = 0; i < 4; i++)
393e12c5d1SDavid du Colombier 		val = val<<8 | getmem_b(addr++);
403e12c5d1SDavid du Colombier 	return val;
413e12c5d1SDavid du Colombier }
423e12c5d1SDavid du Colombier 
433e12c5d1SDavid du Colombier ulong
getmem_2(ulong addr)443e12c5d1SDavid du Colombier getmem_2(ulong addr)
453e12c5d1SDavid du Colombier {
463e12c5d1SDavid du Colombier 	ulong val;
473e12c5d1SDavid du Colombier 
483e12c5d1SDavid du Colombier 	val = getmem_b(addr);
493e12c5d1SDavid du Colombier 	val = val<<8 | getmem_b(addr+1);
503e12c5d1SDavid du Colombier 
513e12c5d1SDavid du Colombier 	return val;
523e12c5d1SDavid du Colombier }
533e12c5d1SDavid du Colombier 
543e12c5d1SDavid du Colombier ulong
getmem_w(ulong addr)553e12c5d1SDavid du Colombier getmem_w(ulong addr)
563e12c5d1SDavid du Colombier {
573e12c5d1SDavid du Colombier 	uchar *va;
583e12c5d1SDavid du Colombier 
593e12c5d1SDavid du Colombier 	if(addr&3) {
603e12c5d1SDavid du Colombier 		Bprint(bioout, "Address error (Load) vaddr %.8lux\n", addr);
613e12c5d1SDavid du Colombier 		longjmp(errjmp, 0);
623e12c5d1SDavid du Colombier 	}
633e12c5d1SDavid du Colombier 	if(membpt)
643e12c5d1SDavid du Colombier 		brkchk(addr, Read);
653e12c5d1SDavid du Colombier 
663e12c5d1SDavid du Colombier 	va = vaddr(addr);
673e12c5d1SDavid du Colombier 	va += addr&(BY2PG-1);
683e12c5d1SDavid du Colombier 
693e12c5d1SDavid du Colombier 	return va[0]<<24 | va[1]<<16 | va[2]<<8 | va[3];;
703e12c5d1SDavid du Colombier }
713e12c5d1SDavid du Colombier 
723e12c5d1SDavid du Colombier ushort
getmem_h(ulong addr)733e12c5d1SDavid du Colombier getmem_h(ulong addr)
743e12c5d1SDavid du Colombier {
753e12c5d1SDavid du Colombier 	uchar *va;
763e12c5d1SDavid du Colombier 
773e12c5d1SDavid du Colombier 	if(addr&1) {
783e12c5d1SDavid du Colombier 		Bprint(bioout, "Address error (Load) vaddr %.8lux\n", addr);
793e12c5d1SDavid du Colombier 		longjmp(errjmp, 0);
803e12c5d1SDavid du Colombier 	}
813e12c5d1SDavid du Colombier 	if(membpt)
823e12c5d1SDavid du Colombier 		brkchk(addr, Read);
833e12c5d1SDavid du Colombier 
843e12c5d1SDavid du Colombier 	va = vaddr(addr);
853e12c5d1SDavid du Colombier 	va += addr&(BY2PG-1);
863e12c5d1SDavid du Colombier 
873e12c5d1SDavid du Colombier 	return va[0]<<8 | va[1];
883e12c5d1SDavid du Colombier }
893e12c5d1SDavid du Colombier 
903e12c5d1SDavid du Colombier uchar
getmem_b(ulong addr)913e12c5d1SDavid du Colombier getmem_b(ulong addr)
923e12c5d1SDavid du Colombier {
933e12c5d1SDavid du Colombier 	uchar *va;
943e12c5d1SDavid du Colombier 
953e12c5d1SDavid du Colombier 	if(membpt)
963e12c5d1SDavid du Colombier 		brkchk(addr, Read);
973e12c5d1SDavid du Colombier 
983e12c5d1SDavid du Colombier 	va = vaddr(addr);
993e12c5d1SDavid du Colombier 	va += addr&(BY2PG-1);
1003e12c5d1SDavid du Colombier 	return va[0];
1013e12c5d1SDavid du Colombier }
1023e12c5d1SDavid du Colombier 
1033e12c5d1SDavid du Colombier void
putmem_w(ulong addr,ulong data)1043e12c5d1SDavid du Colombier putmem_w(ulong addr, ulong data)
1053e12c5d1SDavid du Colombier {
1063e12c5d1SDavid du Colombier 	uchar *va;
1073e12c5d1SDavid du Colombier 
1083e12c5d1SDavid du Colombier 	if(addr&3) {
1093e12c5d1SDavid du Colombier 		Bprint(bioout, "Address error (Store) vaddr %.8lux\n", addr);
1103e12c5d1SDavid du Colombier 		longjmp(errjmp, 0);
1113e12c5d1SDavid du Colombier 	}
1123e12c5d1SDavid du Colombier 
1133e12c5d1SDavid du Colombier 	va = vaddr(addr);
1143e12c5d1SDavid du Colombier 	va += addr&(BY2PG-1);
1153e12c5d1SDavid du Colombier 
1163e12c5d1SDavid du Colombier 	va[0] = data>>24;
1173e12c5d1SDavid du Colombier 	va[1] = data>>16;
1183e12c5d1SDavid du Colombier 	va[2] = data>>8;
1193e12c5d1SDavid du Colombier 	va[3] = data;
1203e12c5d1SDavid du Colombier 	if(membpt)
1213e12c5d1SDavid du Colombier 		brkchk(addr, Write);
1223e12c5d1SDavid du Colombier }
1233e12c5d1SDavid du Colombier void
putmem_b(ulong addr,uchar data)1243e12c5d1SDavid du Colombier putmem_b(ulong addr, uchar data)
1253e12c5d1SDavid du Colombier {
1263e12c5d1SDavid du Colombier 	uchar *va;
1273e12c5d1SDavid du Colombier 
1283e12c5d1SDavid du Colombier 	va = vaddr(addr);
1293e12c5d1SDavid du Colombier 	va += addr&(BY2PG-1);
1303e12c5d1SDavid du Colombier 	va[0] = data;
1313e12c5d1SDavid du Colombier 	if(membpt)
1323e12c5d1SDavid du Colombier 		brkchk(addr, Write);
1333e12c5d1SDavid du Colombier }
1343e12c5d1SDavid du Colombier 
1353e12c5d1SDavid du Colombier void
putmem_h(ulong addr,short data)1363e12c5d1SDavid du Colombier putmem_h(ulong addr, short data)
1373e12c5d1SDavid du Colombier {
1383e12c5d1SDavid du Colombier 	uchar *va;
1393e12c5d1SDavid du Colombier 
1403e12c5d1SDavid du Colombier 	if(addr&1) {
1413e12c5d1SDavid du Colombier 		Bprint(bioout, "Address error (Store) vaddr %.8lux\n", addr);
1423e12c5d1SDavid du Colombier 		longjmp(errjmp, 0);
1433e12c5d1SDavid du Colombier 	}
1443e12c5d1SDavid du Colombier 
1453e12c5d1SDavid du Colombier 	va = vaddr(addr);
1463e12c5d1SDavid du Colombier 	va += addr&(BY2PG-1);
1473e12c5d1SDavid du Colombier 	va[0] = data>>8;
1483e12c5d1SDavid du Colombier 	va[1] = data;
1493e12c5d1SDavid du Colombier 	if(membpt)
1503e12c5d1SDavid du Colombier 		brkchk(addr, Write);
1513e12c5d1SDavid du Colombier }
1523e12c5d1SDavid du Colombier 
1533e12c5d1SDavid du Colombier char *
memio(char * mb,ulong mem,int size,int dir)1543e12c5d1SDavid du Colombier memio(char *mb, ulong mem, int size, int dir)
1553e12c5d1SDavid du Colombier {
1563e12c5d1SDavid du Colombier 	int i;
1573e12c5d1SDavid du Colombier 	char *buf, c;
1583e12c5d1SDavid du Colombier 
1593e12c5d1SDavid du Colombier 	if(mb == 0)
1603e12c5d1SDavid du Colombier 		mb = emalloc(size);
1613e12c5d1SDavid du Colombier 
1623e12c5d1SDavid du Colombier 	buf = mb;
1633e12c5d1SDavid du Colombier 	switch(dir) {
1643e12c5d1SDavid du Colombier 	default:
1653e12c5d1SDavid du Colombier 		fatal(0, "memio");
1663e12c5d1SDavid du Colombier 	case MemRead:
1673e12c5d1SDavid du Colombier 		while(size--)
1683e12c5d1SDavid du Colombier 			*mb++ = getmem_b(mem++);
1693e12c5d1SDavid du Colombier 		break;
1703e12c5d1SDavid du Colombier 	case MemReadstring:
1713e12c5d1SDavid du Colombier 		for(;;) {
1723e12c5d1SDavid du Colombier 			if(size-- == 0) {
1733e12c5d1SDavid du Colombier 				Bprint(bioout, "memio: user/kernel copy too long for mipsim\n");
1743e12c5d1SDavid du Colombier 				longjmp(errjmp, 0);
1753e12c5d1SDavid du Colombier 			}
1763e12c5d1SDavid du Colombier 			c = getmem_b(mem++);
1773e12c5d1SDavid du Colombier 			*mb++ = c;
1783e12c5d1SDavid du Colombier 			if(c == '\0')
1793e12c5d1SDavid du Colombier 				break;
1803e12c5d1SDavid du Colombier 		}
1813e12c5d1SDavid du Colombier 		break;
1823e12c5d1SDavid du Colombier 	case MemWrite:
1833e12c5d1SDavid du Colombier 		for(i = 0; i < size; i++)
1843e12c5d1SDavid du Colombier 			putmem_b(mem++, *mb++);
1853e12c5d1SDavid du Colombier 		break;
1863e12c5d1SDavid du Colombier 	}
1873e12c5d1SDavid du Colombier 	return buf;
1883e12c5d1SDavid du Colombier }
1893e12c5d1SDavid du Colombier 
1903e12c5d1SDavid du Colombier void
dotlb(ulong vaddr)1913e12c5d1SDavid du Colombier dotlb(ulong vaddr)
1923e12c5d1SDavid du Colombier {
1933e12c5d1SDavid du Colombier 	ulong *l, *e;
1943e12c5d1SDavid du Colombier 
1953e12c5d1SDavid du Colombier 	vaddr &= ~(BY2PG-1);
1963e12c5d1SDavid du Colombier 
1973e12c5d1SDavid du Colombier 	e = &tlb.tlbent[tlb.tlbsize];
1983e12c5d1SDavid du Colombier 	for(l = tlb.tlbent; l < e; l++)
1993e12c5d1SDavid du Colombier 		if(*l == vaddr) {
2003e12c5d1SDavid du Colombier 			tlb.hit++;
2013e12c5d1SDavid du Colombier 			return;
2023e12c5d1SDavid du Colombier 		}
2033e12c5d1SDavid du Colombier 
2043e12c5d1SDavid du Colombier 	tlb.miss++;
2053e12c5d1SDavid du Colombier 	tlb.tlbent[lnrand(tlb.tlbsize)] = vaddr;
2063e12c5d1SDavid du Colombier }
2073e12c5d1SDavid du Colombier 
2083e12c5d1SDavid du Colombier void*
vaddr1(ulong addr)209*7dd7cddfSDavid du Colombier vaddr1(ulong addr)
2103e12c5d1SDavid du Colombier {
2113e12c5d1SDavid du Colombier 	Segment *s, *es;
2123e12c5d1SDavid du Colombier 	int off, foff, l, n;
2133e12c5d1SDavid du Colombier 	uchar **p, *a;
2143e12c5d1SDavid du Colombier 
2153e12c5d1SDavid du Colombier 	if(tlb.on)
2163e12c5d1SDavid du Colombier 		dotlb(addr);
2173e12c5d1SDavid du Colombier 
2183e12c5d1SDavid du Colombier 	es = &memory.seg[Nseg];
2193e12c5d1SDavid du Colombier 	for(s = memory.seg; s < es; s++) {
2203e12c5d1SDavid du Colombier 		if(addr >= s->base && addr < s->end) {
2213e12c5d1SDavid du Colombier 			s->refs++;
2223e12c5d1SDavid du Colombier 			off = (addr-s->base)/BY2PG;
2233e12c5d1SDavid du Colombier 			p = &s->table[off];
2243e12c5d1SDavid du Colombier 			if(*p)
2253e12c5d1SDavid du Colombier 				return *p;
2263e12c5d1SDavid du Colombier 			s->rss++;
2273e12c5d1SDavid du Colombier 			switch(s->type) {
2283e12c5d1SDavid du Colombier 			default:
2293e12c5d1SDavid du Colombier 				fatal(0, "vaddr");
2303e12c5d1SDavid du Colombier 			case Text:
2313e12c5d1SDavid du Colombier 				*p = emalloc(BY2PG);
2323e12c5d1SDavid du Colombier 				if(seek(text, s->fileoff+(off*BY2PG), 0) < 0)
2333e12c5d1SDavid du Colombier 					fatal(1, "vaddr text seek");
2343e12c5d1SDavid du Colombier 				if(read(text, *p, BY2PG) < 0)
2353e12c5d1SDavid du Colombier 					fatal(1, "vaddr text read");
2363e12c5d1SDavid du Colombier 				return *p;
2373e12c5d1SDavid du Colombier 			case Data:
2383e12c5d1SDavid du Colombier 				*p = emalloc(BY2PG);
2393e12c5d1SDavid du Colombier 				foff = s->fileoff+(off*BY2PG);
2403e12c5d1SDavid du Colombier 				if(seek(text, foff, 0) < 0)
2413e12c5d1SDavid du Colombier 					fatal(1, "vaddr text seek");
2423e12c5d1SDavid du Colombier 				n = read(text, *p, BY2PG);
2433e12c5d1SDavid du Colombier 				if(n < 0)
2443e12c5d1SDavid du Colombier 					fatal(1, "vaddr text read");
2453e12c5d1SDavid du Colombier 				if(foff + n > s->fileend) {
2463e12c5d1SDavid du Colombier 					l = BY2PG - (s->fileend-foff);
2473e12c5d1SDavid du Colombier 					a = *p+(s->fileend-foff);
2483e12c5d1SDavid du Colombier 					memset(a, 0, l);
2493e12c5d1SDavid du Colombier 				}
2503e12c5d1SDavid du Colombier 				return *p;
2513e12c5d1SDavid du Colombier 			case Bss:
2523e12c5d1SDavid du Colombier 			case Stack:
2533e12c5d1SDavid du Colombier 				*p = emalloc(BY2PG);
2543e12c5d1SDavid du Colombier 				return *p;
2553e12c5d1SDavid du Colombier 			}
2563e12c5d1SDavid du Colombier 		}
2573e12c5d1SDavid du Colombier 	}
258*7dd7cddfSDavid du Colombier 	return 0;
259*7dd7cddfSDavid du Colombier }
260*7dd7cddfSDavid du Colombier 
261*7dd7cddfSDavid du Colombier void*
vaddr(ulong addr)262*7dd7cddfSDavid du Colombier vaddr(ulong addr)
263*7dd7cddfSDavid du Colombier {
264*7dd7cddfSDavid du Colombier 	void *v;
265*7dd7cddfSDavid du Colombier 
266*7dd7cddfSDavid du Colombier 	v = vaddr1(addr);
267*7dd7cddfSDavid du Colombier 	if(v == 0) {
2683e12c5d1SDavid du Colombier 		Bprint(bioout, "User TLB miss vaddr 0x%.8lux\n", addr);
2693e12c5d1SDavid du Colombier 		longjmp(errjmp, 0);
270*7dd7cddfSDavid du Colombier 	}
271*7dd7cddfSDavid du Colombier 	return v;
272*7dd7cddfSDavid du Colombier }
273*7dd7cddfSDavid du Colombier 
274*7dd7cddfSDavid du Colombier int
badvaddr(ulong addr,int n)275*7dd7cddfSDavid du Colombier badvaddr(ulong addr, int n)
276*7dd7cddfSDavid du Colombier {
277*7dd7cddfSDavid du Colombier 	void *v;
278*7dd7cddfSDavid du Colombier 
279*7dd7cddfSDavid du Colombier 	if(addr & (n-1))
280*7dd7cddfSDavid du Colombier 		return 1;
281*7dd7cddfSDavid du Colombier 	v = vaddr1(addr);
282*7dd7cddfSDavid du Colombier 	if(v == 0)
283*7dd7cddfSDavid du Colombier 		return 1;
284*7dd7cddfSDavid du Colombier 	return 0;
2853e12c5d1SDavid du Colombier }
286