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