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