Give an opaque to the m48t59 direct access routines to make it easier
[qemu] / target-cris / mmu.c
1 /*
2  *  CRIS mmu emulation.
3  *
4  *  Copyright (c) 2007 AXIS Communications AB
5  *  Written by Edgar E. Iglesias.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #ifndef CONFIG_USER_ONLY
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27
28 #include "config.h"
29 #include "cpu.h"
30 #include "mmu.h"
31 #include "exec-all.h"
32
33
34 static int cris_mmu_enabled(uint32_t rw_gc_cfg)
35 {
36         return (rw_gc_cfg & 12) != 0;
37 }
38
39 static int cris_mmu_segmented_addr(int seg, uint32_t rw_mm_cfg)
40 {
41         return (1 << seg) & rw_mm_cfg;
42 }
43
44 static uint32_t cris_mmu_translate_seg(CPUState *env, int seg)
45 {
46         uint32_t base;
47         int i;
48
49         if (seg < 8)
50                 base = env->sregs[SFR_RW_MM_KBASE_LO];
51         else
52                 base = env->sregs[SFR_RW_MM_KBASE_HI];
53
54         i = seg & 7;
55         base >>= i * 4;
56         base &= 15;
57
58         base <<= 28;
59         return base;
60 }
61 /* Used by the tlb decoder.  */
62 #define EXTRACT_FIELD(src, start, end) \
63             (((src) >> start) & ((1 << (end - start + 1)) - 1))
64
65 static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
66                                    CPUState *env, uint32_t vaddr,
67                                    int rw, int usermode)
68 {
69         unsigned int vpage;
70         unsigned int idx;
71         uint32_t lo, hi;
72         uint32_t vpn, pfn = 0, pid, fg, fv, fk, fw, fx;
73         int i, match = 0;
74
75         vpage = vaddr >> 13;
76         idx = vpage & 31;
77         vpage >>= 4;
78
79         /* We know the index which to check on each set.
80            Scan both I and D.  */
81         for (i = 0; i < 4; i++)
82         {
83                 lo = env->tlbsets[0][i][idx].lo;
84                 hi = env->tlbsets[0][i][idx].hi;
85
86                 vpn = EXTRACT_FIELD(hi, 13, 31);
87                 pid = EXTRACT_FIELD(hi, 0, 7);
88
89                 if (vpn == vpage
90                     && pid == env->pregs[SR_PID]) {
91                         match = 1;
92                         break;
93                 }
94         }
95
96         if (match) {
97                 pfn = EXTRACT_FIELD(lo, 13, 31);
98                 fg = EXTRACT_FIELD(lo, 4, 4);
99                 fv = EXTRACT_FIELD(lo, 3, 3);
100                 fk = EXTRACT_FIELD(lo, 2, 2);
101                 fw = EXTRACT_FIELD(lo, 1, 1);
102                 fx = EXTRACT_FIELD(lo, 0, 0);
103         }
104         printf ("%s match=%d vaddr=%x vpage=%x vpn=%x pfn=%x pid=%x %x\n",
105                 __func__, match,
106                 vaddr, vpage,
107                 vpn, pfn, pid, env->pregs[SR_PID]);
108         res->pfn = pfn;
109         return !match;
110 }
111
112 int cris_mmu_translate(struct cris_mmu_result_t *res,
113                        CPUState *env, uint32_t vaddr,
114                        int rw, int mmu_idx)
115 {
116         uint32_t phy = vaddr;
117         int seg;
118         int miss = 0;
119         int is_user = mmu_idx == MMU_USER_IDX;
120
121         if (!cris_mmu_enabled(env->sregs[SFR_RW_GC_CFG])) {
122                 res->phy = vaddr;
123                 return 0;
124         }
125
126         seg = vaddr >> 28;
127         if (cris_mmu_segmented_addr(seg, env->sregs[SFR_RW_MM_CFG]))
128         {
129                 uint32_t base;
130
131                 miss = 0;
132                 base = cris_mmu_translate_seg(env, seg);
133                 phy = base | (0x0fffffff & vaddr);
134                 res->phy = phy;
135         }
136         else
137         {
138                 miss = cris_mmu_translate_page(res, env, vaddr, rw, is_user);
139                 if (!miss) {
140                         phy &= 8191;
141                         phy |= (res->pfn << 13);
142                         res->phy = phy;
143                 }
144         }
145 //      printf ("miss=%d v=%x -> p=%x\n", miss, vaddr, phy);
146         return miss;
147 }
148 #endif