xref: /qemu/target/microblaze/mmu.c (revision 0f96e96b)
1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth  *  Microblaze MMU emulation for qemu.
3fcf5ef2aSThomas Huth  *
4fcf5ef2aSThomas Huth  *  Copyright (c) 2009 Edgar E. Iglesias
5fcf5ef2aSThomas Huth  *  Copyright (c) 2009-2012 PetaLogix Qld Pty Ltd.
6fcf5ef2aSThomas Huth  *
7fcf5ef2aSThomas Huth  * This library is free software; you can redistribute it and/or
8fcf5ef2aSThomas Huth  * modify it under the terms of the GNU Lesser General Public
9fcf5ef2aSThomas Huth  * License as published by the Free Software Foundation; either
10fcf5ef2aSThomas Huth  * version 2 of the License, or (at your option) any later version.
11fcf5ef2aSThomas Huth  *
12fcf5ef2aSThomas Huth  * This library is distributed in the hope that it will be useful,
13fcf5ef2aSThomas Huth  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14fcf5ef2aSThomas Huth  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15fcf5ef2aSThomas Huth  * Lesser General Public License for more details.
16fcf5ef2aSThomas Huth  *
17fcf5ef2aSThomas Huth  * You should have received a copy of the GNU Lesser General Public
18fcf5ef2aSThomas Huth  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19fcf5ef2aSThomas Huth  */
20fcf5ef2aSThomas Huth 
21fcf5ef2aSThomas Huth #include "qemu/osdep.h"
22fcf5ef2aSThomas Huth #include "cpu.h"
23fcf5ef2aSThomas Huth #include "exec/exec-all.h"
24fcf5ef2aSThomas Huth 
25fcf5ef2aSThomas Huth static unsigned int tlb_decode_size(unsigned int f)
26fcf5ef2aSThomas Huth {
27fcf5ef2aSThomas Huth     static const unsigned int sizes[] = {
28fcf5ef2aSThomas Huth         1 * 1024, 4 * 1024, 16 * 1024, 64 * 1024, 256 * 1024,
29fcf5ef2aSThomas Huth         1 * 1024 * 1024, 4 * 1024 * 1024, 16 * 1024 * 1024
30fcf5ef2aSThomas Huth     };
31fcf5ef2aSThomas Huth     assert(f < ARRAY_SIZE(sizes));
32fcf5ef2aSThomas Huth     return sizes[f];
33fcf5ef2aSThomas Huth }
34fcf5ef2aSThomas Huth 
35fcf5ef2aSThomas Huth static void mmu_flush_idx(CPUMBState *env, unsigned int idx)
36fcf5ef2aSThomas Huth {
37f5c7e93aSRichard Henderson     CPUState *cs = env_cpu(env);
38fcf5ef2aSThomas Huth     struct microblaze_mmu *mmu = &env->mmu;
39fcf5ef2aSThomas Huth     unsigned int tlb_size;
40fcf5ef2aSThomas Huth     uint32_t tlb_tag, end, t;
41fcf5ef2aSThomas Huth 
42fcf5ef2aSThomas Huth     t = mmu->rams[RAM_TAG][idx];
43fcf5ef2aSThomas Huth     if (!(t & TLB_VALID))
44fcf5ef2aSThomas Huth         return;
45fcf5ef2aSThomas Huth 
46fcf5ef2aSThomas Huth     tlb_tag = t & TLB_EPN_MASK;
47fcf5ef2aSThomas Huth     tlb_size = tlb_decode_size((t & TLB_PAGESZ_MASK) >> 7);
48fcf5ef2aSThomas Huth     end = tlb_tag + tlb_size;
49fcf5ef2aSThomas Huth 
50fcf5ef2aSThomas Huth     while (tlb_tag < end) {
51fcf5ef2aSThomas Huth         tlb_flush_page(cs, tlb_tag);
52fcf5ef2aSThomas Huth         tlb_tag += TARGET_PAGE_SIZE;
53fcf5ef2aSThomas Huth     }
54fcf5ef2aSThomas Huth }
55fcf5ef2aSThomas Huth 
56fcf5ef2aSThomas Huth static void mmu_change_pid(CPUMBState *env, unsigned int newpid)
57fcf5ef2aSThomas Huth {
58fcf5ef2aSThomas Huth     struct microblaze_mmu *mmu = &env->mmu;
59fcf5ef2aSThomas Huth     unsigned int i;
60fcf5ef2aSThomas Huth     uint32_t t;
61fcf5ef2aSThomas Huth 
62fcf5ef2aSThomas Huth     if (newpid & ~0xff)
63fcf5ef2aSThomas Huth         qemu_log_mask(LOG_GUEST_ERROR, "Illegal rpid=%x\n", newpid);
64fcf5ef2aSThomas Huth 
65fcf5ef2aSThomas Huth     for (i = 0; i < ARRAY_SIZE(mmu->rams[RAM_TAG]); i++) {
66fcf5ef2aSThomas Huth         /* Lookup and decode.  */
67fcf5ef2aSThomas Huth         t = mmu->rams[RAM_TAG][i];
68fcf5ef2aSThomas Huth         if (t & TLB_VALID) {
69fcf5ef2aSThomas Huth             if (mmu->tids[i] && ((mmu->regs[MMU_R_PID] & 0xff) == mmu->tids[i]))
70fcf5ef2aSThomas Huth                 mmu_flush_idx(env, i);
71fcf5ef2aSThomas Huth         }
72fcf5ef2aSThomas Huth     }
73fcf5ef2aSThomas Huth }
74fcf5ef2aSThomas Huth 
75fcf5ef2aSThomas Huth /* rw - 0 = read, 1 = write, 2 = fetch.  */
76fcf5ef2aSThomas Huth unsigned int mmu_translate(struct microblaze_mmu *mmu,
77fcf5ef2aSThomas Huth                            struct microblaze_mmu_lookup *lu,
78fcf5ef2aSThomas Huth                            target_ulong vaddr, int rw, int mmu_idx)
79fcf5ef2aSThomas Huth {
80fcf5ef2aSThomas Huth     unsigned int i, hit = 0;
81fcf5ef2aSThomas Huth     unsigned int tlb_ex = 0, tlb_wr = 0, tlb_zsel;
82d2f004c3SEdgar E. Iglesias     uint64_t tlb_tag, tlb_rpn, mask;
83d2f004c3SEdgar E. Iglesias     uint32_t tlb_size, t0;
84fcf5ef2aSThomas Huth 
85fcf5ef2aSThomas Huth     lu->err = ERR_MISS;
86fcf5ef2aSThomas Huth     for (i = 0; i < ARRAY_SIZE(mmu->rams[RAM_TAG]); i++) {
87d2f004c3SEdgar E. Iglesias         uint64_t t, d;
88fcf5ef2aSThomas Huth 
89fcf5ef2aSThomas Huth         /* Lookup and decode.  */
90fcf5ef2aSThomas Huth         t = mmu->rams[RAM_TAG][i];
91fcf5ef2aSThomas Huth         if (t & TLB_VALID) {
92fcf5ef2aSThomas Huth             tlb_size = tlb_decode_size((t & TLB_PAGESZ_MASK) >> 7);
93fcf5ef2aSThomas Huth             if (tlb_size < TARGET_PAGE_SIZE) {
9475c9ddceSEdgar E. Iglesias                 qemu_log_mask(LOG_UNIMP, "%d pages not supported\n", tlb_size);
95fcf5ef2aSThomas Huth                 abort();
96fcf5ef2aSThomas Huth             }
97fcf5ef2aSThomas Huth 
98d2f004c3SEdgar E. Iglesias             mask = ~((uint64_t)tlb_size - 1);
99fcf5ef2aSThomas Huth             tlb_tag = t & TLB_EPN_MASK;
100fcf5ef2aSThomas Huth             if ((vaddr & mask) != (tlb_tag & mask)) {
101fcf5ef2aSThomas Huth                 continue;
102fcf5ef2aSThomas Huth             }
103fcf5ef2aSThomas Huth             if (mmu->tids[i]
104fcf5ef2aSThomas Huth                 && ((mmu->regs[MMU_R_PID] & 0xff) != mmu->tids[i])) {
105fcf5ef2aSThomas Huth                 continue;
106fcf5ef2aSThomas Huth             }
107fcf5ef2aSThomas Huth 
108fcf5ef2aSThomas Huth             /* Bring in the data part.  */
109fcf5ef2aSThomas Huth             d = mmu->rams[RAM_DATA][i];
110fcf5ef2aSThomas Huth             tlb_ex = d & TLB_EX;
111fcf5ef2aSThomas Huth             tlb_wr = d & TLB_WR;
112fcf5ef2aSThomas Huth 
113fcf5ef2aSThomas Huth             /* Now let's see if there is a zone that overrides the protbits.  */
114fcf5ef2aSThomas Huth             tlb_zsel = (d >> 4) & 0xf;
115fcf5ef2aSThomas Huth             t0 = mmu->regs[MMU_R_ZPR] >> (30 - (tlb_zsel * 2));
116fcf5ef2aSThomas Huth             t0 &= 0x3;
117fcf5ef2aSThomas Huth 
118fcf5ef2aSThomas Huth             if (tlb_zsel > mmu->c_mmu_zones) {
11975c9ddceSEdgar E. Iglesias                 qemu_log_mask(LOG_GUEST_ERROR,
12075c9ddceSEdgar E. Iglesias                               "tlb zone select out of range! %d\n", tlb_zsel);
121fcf5ef2aSThomas Huth                 t0 = 1; /* Ignore.  */
122fcf5ef2aSThomas Huth             }
123fcf5ef2aSThomas Huth 
124fcf5ef2aSThomas Huth             if (mmu->c_mmu == 1) {
125fcf5ef2aSThomas Huth                 t0 = 1; /* Zones are disabled.  */
126fcf5ef2aSThomas Huth             }
127fcf5ef2aSThomas Huth 
128fcf5ef2aSThomas Huth             switch (t0) {
129fcf5ef2aSThomas Huth                 case 0:
130fcf5ef2aSThomas Huth                     if (mmu_idx == MMU_USER_IDX)
131fcf5ef2aSThomas Huth                         continue;
132fcf5ef2aSThomas Huth                     break;
133fcf5ef2aSThomas Huth                 case 2:
134fcf5ef2aSThomas Huth                     if (mmu_idx != MMU_USER_IDX) {
135fcf5ef2aSThomas Huth                         tlb_ex = 1;
136fcf5ef2aSThomas Huth                         tlb_wr = 1;
137fcf5ef2aSThomas Huth                     }
138fcf5ef2aSThomas Huth                     break;
139fcf5ef2aSThomas Huth                 case 3:
140fcf5ef2aSThomas Huth                     tlb_ex = 1;
141fcf5ef2aSThomas Huth                     tlb_wr = 1;
142fcf5ef2aSThomas Huth                     break;
143fcf5ef2aSThomas Huth                 default: break;
144fcf5ef2aSThomas Huth             }
145fcf5ef2aSThomas Huth 
146fcf5ef2aSThomas Huth             lu->err = ERR_PROT;
147fcf5ef2aSThomas Huth             lu->prot = PAGE_READ;
148fcf5ef2aSThomas Huth             if (tlb_wr)
149fcf5ef2aSThomas Huth                 lu->prot |= PAGE_WRITE;
150fcf5ef2aSThomas Huth             else if (rw == 1)
151fcf5ef2aSThomas Huth                 goto done;
152fcf5ef2aSThomas Huth             if (tlb_ex)
153fcf5ef2aSThomas Huth                 lu->prot |=PAGE_EXEC;
154fcf5ef2aSThomas Huth             else if (rw == 2) {
155fcf5ef2aSThomas Huth                 goto done;
156fcf5ef2aSThomas Huth             }
157fcf5ef2aSThomas Huth 
158fcf5ef2aSThomas Huth             tlb_rpn = d & TLB_RPN_MASK;
159fcf5ef2aSThomas Huth 
160fcf5ef2aSThomas Huth             lu->vaddr = tlb_tag;
1613924a9aaSEdgar E. Iglesias             lu->paddr = tlb_rpn & mmu->c_addr_mask;
162fcf5ef2aSThomas Huth             lu->size = tlb_size;
163fcf5ef2aSThomas Huth             lu->err = ERR_HIT;
164fcf5ef2aSThomas Huth             lu->idx = i;
165fcf5ef2aSThomas Huth             hit = 1;
166fcf5ef2aSThomas Huth             goto done;
167fcf5ef2aSThomas Huth         }
168fcf5ef2aSThomas Huth     }
169fcf5ef2aSThomas Huth done:
17075c9ddceSEdgar E. Iglesias     qemu_log_mask(CPU_LOG_MMU,
17175c9ddceSEdgar E. Iglesias                   "MMU vaddr=%" PRIx64 " rw=%d tlb_wr=%d tlb_ex=%d hit=%d\n",
17275c9ddceSEdgar E. Iglesias                   vaddr, rw, tlb_wr, tlb_ex, hit);
173fcf5ef2aSThomas Huth     return hit;
174fcf5ef2aSThomas Huth }
175fcf5ef2aSThomas Huth 
176fcf5ef2aSThomas Huth /* Writes/reads to the MMU's special regs end up here.  */
177f0f7e7f7SEdgar E. Iglesias uint32_t mmu_read(CPUMBState *env, bool ext, uint32_t rn)
178fcf5ef2aSThomas Huth {
179fcf5ef2aSThomas Huth     unsigned int i;
180bd9e6608SEdgar E. Iglesias     uint32_t r = 0;
181fcf5ef2aSThomas Huth 
182fcf5ef2aSThomas Huth     if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) {
183fcf5ef2aSThomas Huth         qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n");
184fcf5ef2aSThomas Huth         return 0;
185fcf5ef2aSThomas Huth     }
186f0f7e7f7SEdgar E. Iglesias     if (ext && rn != MMU_R_TLBLO) {
187f0f7e7f7SEdgar E. Iglesias         qemu_log_mask(LOG_GUEST_ERROR, "Extended access only to TLBLO.\n");
188f0f7e7f7SEdgar E. Iglesias         return 0;
189f0f7e7f7SEdgar E. Iglesias     }
190fcf5ef2aSThomas Huth 
191fcf5ef2aSThomas Huth     switch (rn) {
192fcf5ef2aSThomas Huth         /* Reads to HI/LO trig reads from the mmu rams.  */
193fcf5ef2aSThomas Huth         case MMU_R_TLBLO:
194fcf5ef2aSThomas Huth         case MMU_R_TLBHI:
195fcf5ef2aSThomas Huth             if (!(env->mmu.c_mmu_tlb_access & 1)) {
19675c9ddceSEdgar E. Iglesias                 qemu_log_mask(LOG_GUEST_ERROR,
19775c9ddceSEdgar E. Iglesias                               "Invalid access to MMU reg %d\n", rn);
198fcf5ef2aSThomas Huth                 return 0;
199fcf5ef2aSThomas Huth             }
200fcf5ef2aSThomas Huth 
201fcf5ef2aSThomas Huth             i = env->mmu.regs[MMU_R_TLBX] & 0xff;
202f0f7e7f7SEdgar E. Iglesias             r = extract64(env->mmu.rams[rn & 1][i], ext * 32, 32);
203fcf5ef2aSThomas Huth             if (rn == MMU_R_TLBHI)
204fcf5ef2aSThomas Huth                 env->mmu.regs[MMU_R_PID] = env->mmu.tids[i];
205fcf5ef2aSThomas Huth             break;
206fcf5ef2aSThomas Huth         case MMU_R_PID:
207fcf5ef2aSThomas Huth         case MMU_R_ZPR:
208fcf5ef2aSThomas Huth             if (!(env->mmu.c_mmu_tlb_access & 1)) {
20975c9ddceSEdgar E. Iglesias                 qemu_log_mask(LOG_GUEST_ERROR,
21075c9ddceSEdgar E. Iglesias                               "Invalid access to MMU reg %d\n", rn);
211fcf5ef2aSThomas Huth                 return 0;
212fcf5ef2aSThomas Huth             }
213fcf5ef2aSThomas Huth             r = env->mmu.regs[rn];
214fcf5ef2aSThomas Huth             break;
21596716533SEdgar E. Iglesias         case MMU_R_TLBX:
21696716533SEdgar E. Iglesias             r = env->mmu.regs[rn];
21796716533SEdgar E. Iglesias             break;
218bd9e6608SEdgar E. Iglesias         case MMU_R_TLBSX:
219bd9e6608SEdgar E. Iglesias             qemu_log_mask(LOG_GUEST_ERROR, "TLBSX is write-only.\n");
220bd9e6608SEdgar E. Iglesias             break;
221fcf5ef2aSThomas Huth         default:
22296716533SEdgar E. Iglesias             qemu_log_mask(LOG_GUEST_ERROR, "Invalid MMU register %d.\n", rn);
223fcf5ef2aSThomas Huth             break;
224fcf5ef2aSThomas Huth     }
22575c9ddceSEdgar E. Iglesias     qemu_log_mask(CPU_LOG_MMU, "%s rn=%d=%x\n", __func__, rn, r);
226fcf5ef2aSThomas Huth     return r;
227fcf5ef2aSThomas Huth }
228fcf5ef2aSThomas Huth 
229f0f7e7f7SEdgar E. Iglesias void mmu_write(CPUMBState *env, bool ext, uint32_t rn, uint32_t v)
230fcf5ef2aSThomas Huth {
231f0f7e7f7SEdgar E. Iglesias     uint64_t tmp64;
232fcf5ef2aSThomas Huth     unsigned int i;
23375c9ddceSEdgar E. Iglesias     qemu_log_mask(CPU_LOG_MMU,
23475c9ddceSEdgar E. Iglesias                   "%s rn=%d=%x old=%x\n", __func__, rn, v, env->mmu.regs[rn]);
235fcf5ef2aSThomas Huth 
236fcf5ef2aSThomas Huth     if (env->mmu.c_mmu < 2 || !env->mmu.c_mmu_tlb_access) {
237fcf5ef2aSThomas Huth         qemu_log_mask(LOG_GUEST_ERROR, "MMU access on MMU-less system\n");
238fcf5ef2aSThomas Huth         return;
239fcf5ef2aSThomas Huth     }
240f0f7e7f7SEdgar E. Iglesias     if (ext && rn != MMU_R_TLBLO) {
241f0f7e7f7SEdgar E. Iglesias         qemu_log_mask(LOG_GUEST_ERROR, "Extended access only to TLBLO.\n");
242f0f7e7f7SEdgar E. Iglesias         return;
243f0f7e7f7SEdgar E. Iglesias     }
244fcf5ef2aSThomas Huth 
245fcf5ef2aSThomas Huth     switch (rn) {
246fcf5ef2aSThomas Huth         /* Writes to HI/LO trig writes to the mmu rams.  */
247fcf5ef2aSThomas Huth         case MMU_R_TLBLO:
248fcf5ef2aSThomas Huth         case MMU_R_TLBHI:
249fcf5ef2aSThomas Huth             i = env->mmu.regs[MMU_R_TLBX] & 0xff;
250fcf5ef2aSThomas Huth             if (rn == MMU_R_TLBHI) {
251fcf5ef2aSThomas Huth                 if (i < 3 && !(v & TLB_VALID) && qemu_loglevel_mask(~0))
2520a22f8cfSEdgar E. Iglesias                     qemu_log_mask(LOG_GUEST_ERROR,
253*0f96e96bSRichard Henderson                                   "invalidating index %x at pc=%x\n",
25476e8187dSRichard Henderson                                   i, env->pc);
255fcf5ef2aSThomas Huth                 env->mmu.tids[i] = env->mmu.regs[MMU_R_PID] & 0xff;
256fcf5ef2aSThomas Huth                 mmu_flush_idx(env, i);
257fcf5ef2aSThomas Huth             }
258f0f7e7f7SEdgar E. Iglesias             tmp64 = env->mmu.rams[rn & 1][i];
259f0f7e7f7SEdgar E. Iglesias             env->mmu.rams[rn & 1][i] = deposit64(tmp64, ext * 32, 32, v);
260fcf5ef2aSThomas Huth             break;
261fcf5ef2aSThomas Huth         case MMU_R_ZPR:
262fcf5ef2aSThomas Huth             if (env->mmu.c_mmu_tlb_access <= 1) {
26375c9ddceSEdgar E. Iglesias                 qemu_log_mask(LOG_GUEST_ERROR,
26475c9ddceSEdgar E. Iglesias                               "Invalid access to MMU reg %d\n", rn);
265fcf5ef2aSThomas Huth                 return;
266fcf5ef2aSThomas Huth             }
267fcf5ef2aSThomas Huth 
268fcf5ef2aSThomas Huth             /* Changes to the zone protection reg flush the QEMU TLB.
269fcf5ef2aSThomas Huth                Fortunately, these are very uncommon.  */
270fcf5ef2aSThomas Huth             if (v != env->mmu.regs[rn]) {
271f5c7e93aSRichard Henderson                 tlb_flush(env_cpu(env));
272fcf5ef2aSThomas Huth             }
273fcf5ef2aSThomas Huth             env->mmu.regs[rn] = v;
274fcf5ef2aSThomas Huth             break;
275fcf5ef2aSThomas Huth         case MMU_R_PID:
276fcf5ef2aSThomas Huth             if (env->mmu.c_mmu_tlb_access <= 1) {
27775c9ddceSEdgar E. Iglesias                 qemu_log_mask(LOG_GUEST_ERROR,
27875c9ddceSEdgar E. Iglesias                               "Invalid access to MMU reg %d\n", rn);
279fcf5ef2aSThomas Huth                 return;
280fcf5ef2aSThomas Huth             }
281fcf5ef2aSThomas Huth 
282fcf5ef2aSThomas Huth             if (v != env->mmu.regs[rn]) {
283fcf5ef2aSThomas Huth                 mmu_change_pid(env, v);
284fcf5ef2aSThomas Huth                 env->mmu.regs[rn] = v;
285fcf5ef2aSThomas Huth             }
286fcf5ef2aSThomas Huth             break;
287fce6a8ecSEdgar E. Iglesias         case MMU_R_TLBX:
288fce6a8ecSEdgar E. Iglesias             /* Bit 31 is read-only.  */
289fce6a8ecSEdgar E. Iglesias             env->mmu.regs[rn] = deposit32(env->mmu.regs[rn], 0, 31, v);
290fce6a8ecSEdgar E. Iglesias             break;
291fcf5ef2aSThomas Huth         case MMU_R_TLBSX:
292fcf5ef2aSThomas Huth         {
293fcf5ef2aSThomas Huth             struct microblaze_mmu_lookup lu;
294fcf5ef2aSThomas Huth             int hit;
295fcf5ef2aSThomas Huth 
296fcf5ef2aSThomas Huth             if (env->mmu.c_mmu_tlb_access <= 1) {
29775c9ddceSEdgar E. Iglesias                 qemu_log_mask(LOG_GUEST_ERROR,
29875c9ddceSEdgar E. Iglesias                               "Invalid access to MMU reg %d\n", rn);
299fcf5ef2aSThomas Huth                 return;
300fcf5ef2aSThomas Huth             }
301fcf5ef2aSThomas Huth 
302fcf5ef2aSThomas Huth             hit = mmu_translate(&env->mmu, &lu,
303fcf5ef2aSThomas Huth                                 v & TLB_EPN_MASK, 0, cpu_mmu_index(env, false));
304fcf5ef2aSThomas Huth             if (hit) {
305fcf5ef2aSThomas Huth                 env->mmu.regs[MMU_R_TLBX] = lu.idx;
306a2207b59SEdgar E. Iglesias             } else {
307a2207b59SEdgar E. Iglesias                 env->mmu.regs[MMU_R_TLBX] |= R_TBLX_MISS_MASK;
308a2207b59SEdgar E. Iglesias             }
309fcf5ef2aSThomas Huth             break;
310fcf5ef2aSThomas Huth         }
311fcf5ef2aSThomas Huth         default:
31296716533SEdgar E. Iglesias             qemu_log_mask(LOG_GUEST_ERROR, "Invalid MMU register %d.\n", rn);
313fcf5ef2aSThomas Huth             break;
314fcf5ef2aSThomas Huth    }
315fcf5ef2aSThomas Huth }
316fcf5ef2aSThomas Huth 
317fcf5ef2aSThomas Huth void mmu_init(struct microblaze_mmu *mmu)
318fcf5ef2aSThomas Huth {
319fcf5ef2aSThomas Huth     int i;
320fcf5ef2aSThomas Huth     for (i = 0; i < ARRAY_SIZE(mmu->regs); i++) {
321fcf5ef2aSThomas Huth         mmu->regs[i] = 0;
322fcf5ef2aSThomas Huth     }
323fcf5ef2aSThomas Huth }
324