Revision 786c02f1

b/target-cris/cpu.h
35 35
#define EXCP_MMU_READ    1
36 36
#define EXCP_MMU_WRITE   2
37 37
#define EXCP_MMU_FLUSH   3
38
#define EXCP_MMU_MISS    4
38
#define EXCP_MMU_FAULT   4
39 39
#define EXCP_BREAK      16 /* trap.  */
40 40

  
41 41
/* CPU flags.  */
......
110 110
	uint32_t btarget;
111 111
	int btaken;
112 112

  
113
	/* for traps.  */
114
	int trapnr;
115

  
116 113
	/* Condition flag tracking.  */
117 114
	uint32_t cc_op;
118 115
	uint32_t cc_mask;
......
129 126

  
130 127
	int features;
131 128

  
132
        uint64_t pending_interrupts;
133
	int interrupt_request;
134 129
	int exception_index;
130
	int interrupt_request;
131
	int interrupt_vector;
132
	int fault_vector;
133
	int trap_vector;
134

  
135 135
	int user_mode_only;
136 136
	int halted;
137 137

  
......
245 245
#define R_ACR 15
246 246

  
247 247
/* Support regs, P0 - P15  */
248
#define PR_BZ  0
249
#define PR_VR  1
248 250
#define PR_PID 2
249 251
#define PR_SRS 3
252
#define PR_WZ  4
250 253
#define PR_MOF 7
254
#define PR_DZ  8
251 255
#define PR_EBP 9
252 256
#define PR_ERP 10
253 257
#define PR_SRP 11
......
255 259

  
256 260
/* Support function regs.  */
257 261
#define SFR_RW_GC_CFG      0][0
258
#define SFR_RW_MM_CFG      1][0
259
#define SFR_RW_MM_KBASE_LO 1][1
260
#define SFR_RW_MM_KBASE_HI 1][2
261
#define SFR_R_MM_CAUSE     1][3
262
#define SFR_RW_MM_TLB_SEL  1][4
263
#define SFR_RW_MM_TLB_LO   1][5
264
#define SFR_RW_MM_TLB_HI   1][6
262
#define SFR_RW_MM_CFG      2][0
263
#define SFR_RW_MM_KBASE_LO 2][1
264
#define SFR_RW_MM_KBASE_HI 2][2
265
#define SFR_R_MM_CAUSE     2][3
266
#define SFR_RW_MM_TLB_SEL  2][4
267
#define SFR_RW_MM_TLB_LO   2][5
268
#define SFR_RW_MM_TLB_HI   2][6
265 269

  
266 270
#endif
b/target-cris/helper.h
1
#define TCG_HELPER_PROTO
2
void TCG_HELPER_PROTO helper_tlb_update(uint32_t T0);
3

  
b/target-cris/mmu.c
30 30
#include "mmu.h"
31 31
#include "exec-all.h"
32 32

  
33
#define D(x)
33 34

  
34 35
static int cris_mmu_enabled(uint32_t rw_gc_cfg)
35 36
{
......
60 61
}
61 62
/* Used by the tlb decoder.  */
62 63
#define EXTRACT_FIELD(src, start, end) \
63
            (((src) >> start) & ((1 << (end - start + 1)) - 1))
64
	    (((src) >> start) & ((1 << (end - start + 1)) - 1))
65

  
66
static inline void set_field(uint32_t *dst, unsigned int val, 
67
			     unsigned int offset, unsigned int width)
68
{
69
	uint32_t mask;
70

  
71
	mask = (1 << width) - 1;
72
	mask <<= offset;
73
	val <<= offset;
74

  
75
	val &= mask;
76
	D(printf ("val=%x mask=%x dst=%x\n", val, mask, *dst));
77
	*dst &= ~(mask);
78
	*dst |= val;
79
}
64 80

  
65 81
static int cris_mmu_translate_page(struct cris_mmu_result_t *res,
66 82
				   CPUState *env, uint32_t vaddr,
......
69 85
	unsigned int vpage;
70 86
	unsigned int idx;
71 87
	uint32_t lo, hi;
72
	uint32_t vpn, pfn = 0, pid, fg, fv, fk, fw, fx;
88
	uint32_t tlb_vpn, tlb_pfn = 0;
89
	int tlb_pid, tlb_g, tlb_v, tlb_k, tlb_w, tlb_x;
90
	int cfg_v, cfg_k, cfg_w, cfg_x;	
73 91
	int i, match = 0;
92
	uint32_t r_cause;
93
	uint32_t r_cfg;
94
	int rwcause;
95
	int update_sel = 0;
96

  
97
	r_cause = env->sregs[SFR_R_MM_CAUSE];
98
	r_cfg = env->sregs[SFR_RW_MM_CFG];
99
	rwcause = rw ? CRIS_MMU_ERR_WRITE : CRIS_MMU_ERR_READ;
74 100

  
75 101
	vpage = vaddr >> 13;
76
	idx = vpage & 31;
77
	vpage >>= 4;
102
	idx = vpage & 15;
78 103

  
79 104
	/* We know the index which to check on each set.
80 105
	   Scan both I and D.  */
106
#if 0
107
	for (i = 0; i < 4; i++) {
108
		int j;
109
		for (j = 0; j < 16; j++) {
110
			lo = env->tlbsets[1][i][j].lo;
111
			hi = env->tlbsets[1][i][j].hi;
112
			tlb_vpn = EXTRACT_FIELD(hi, 13, 31);
113
			tlb_pfn = EXTRACT_FIELD(lo, 13, 31);
114

  
115
			printf ("TLB: [%d][%d] hi=%x lo=%x v=%x p=%x\n", 
116
					i, j, hi, lo, tlb_vpn, tlb_pfn);
117
		}
118
	}
119
#endif
81 120
	for (i = 0; i < 4; i++)
82 121
	{
83
		lo = env->tlbsets[0][i][idx].lo;
84
		hi = env->tlbsets[0][i][idx].hi;
122
		lo = env->tlbsets[1][i][idx].lo;
123
		hi = env->tlbsets[1][i][idx].hi;
85 124

  
86
		vpn = EXTRACT_FIELD(hi, 13, 31);
87
		pid = EXTRACT_FIELD(hi, 0, 7);
125
		tlb_vpn = EXTRACT_FIELD(hi, 13, 31);
126
		tlb_pfn = EXTRACT_FIELD(lo, 13, 31);
88 127

  
89
		if (vpn == vpage
90
		    && pid == env->pregs[PR_PID]) {
128
		D(printf ("TLB[%d][%d] tlbv=%x vpage=%x -> pfn=%x\n", 
129
				i, idx, tlb_vpn, vpage, tlb_pfn));
130
		if (tlb_vpn == vpage) {
91 131
			match = 1;
92 132
			break;
93 133
		}
94 134
	}
95 135

  
96 136
	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);
137

  
138
		cfg_w  = EXTRACT_FIELD(r_cfg, 19, 19);
139
		cfg_k  = EXTRACT_FIELD(r_cfg, 18, 18);
140
		cfg_x  = EXTRACT_FIELD(r_cfg, 17, 17);
141
		cfg_v  = EXTRACT_FIELD(r_cfg, 16, 16);
142

  
143
		tlb_pid = EXTRACT_FIELD(hi, 0, 7);
144
		tlb_pfn = EXTRACT_FIELD(lo, 13, 31);
145
		tlb_g  = EXTRACT_FIELD(lo, 4, 4);
146
		tlb_v = EXTRACT_FIELD(lo, 3, 3);
147
		tlb_k = EXTRACT_FIELD(lo, 2, 2);
148
		tlb_w = EXTRACT_FIELD(lo, 1, 1);
149
		tlb_x = EXTRACT_FIELD(lo, 0, 0);
150

  
151
		/*
152
		set_exception_vector(0x04, i_mmu_refill);
153
		set_exception_vector(0x05, i_mmu_invalid);
154
		set_exception_vector(0x06, i_mmu_access);
155
		set_exception_vector(0x07, i_mmu_execute);
156
		set_exception_vector(0x08, d_mmu_refill);
157
		set_exception_vector(0x09, d_mmu_invalid);
158
		set_exception_vector(0x0a, d_mmu_access);
159
		set_exception_vector(0x0b, d_mmu_write);
160
		*/
161
		if (cfg_v && !tlb_v) {
162
			printf ("tlb: invalid\n");
163
			set_field(&r_cause, rwcause, 8, 9);
164
			match = 0;
165
			res->bf_vec = 0x9;
166
			update_sel = 1;
167
		}
168
		else if (!tlb_g 
169
			 && tlb_pid != 0xff
170
			 && tlb_pid != env->pregs[PR_PID]
171
			 && cfg_w && !tlb_w) {
172
			printf ("tlb: wrong pid\n");
173
			match = 0;
174
			res->bf_vec = 0xa;
175
		}
176
		else if (rw && cfg_w && !tlb_w) {
177
			printf ("tlb: write protected\n");
178
			match = 0;
179
			res->bf_vec = 0xb;
180
		}
181
	} else
182
		update_sel = 1;
183

  
184
	if (update_sel) {
185
		/* miss.  */
186
		env->sregs[SFR_RW_MM_TLB_SEL] = 0;
187
		D(printf ("tlb: miss %x vp=%x\n", 
188
			env->sregs[SFR_RW_MM_TLB_SEL], vpage & 15));
189
		set_field(&env->sregs[SFR_RW_MM_TLB_SEL], vpage & 15, 0, 4);
190
		set_field(&env->sregs[SFR_RW_MM_TLB_SEL], 0, 4, 5);
191
		res->bf_vec = 0x8;
192
	}
193

  
194
	if (!match) {
195
		set_field(&r_cause, rwcause, 8, 9);
196
		set_field(&r_cause, vpage, 13, 19);
197
		set_field(&r_cause, env->pregs[PR_PID], 0, 8);
198
		env->sregs[SFR_R_MM_CAUSE] = r_cause;
103 199
	}
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[PR_PID]);
108
	res->pfn = pfn;
200
	D(printf ("%s mtch=%d pc=%x va=%x vpn=%x tlbvpn=%x pfn=%x pid=%x"
201
		  " %x cause=%x sel=%x r13=%x\n",
202
		  __func__, match, env->pc,
203
		  vaddr, vpage,
204
		  tlb_vpn, tlb_pfn, tlb_pid, 
205
		  env->pregs[PR_PID],
206
		  r_cause,
207
		  env->sregs[SFR_RW_MM_TLB_SEL],
208
		  env->regs[13]));
209

  
210
	res->pfn = tlb_pfn;
109 211
	return !match;
110 212
}
111 213

  
214
/* Give us the vaddr corresponding to the latest TLB update.  */
215
target_ulong cris_mmu_tlb_latest_update(CPUState *env, uint32_t new_lo)
216
{
217
	uint32_t sel = env->sregs[SFR_RW_MM_TLB_SEL];
218
	uint32_t vaddr;
219
	uint32_t hi;
220
	int set;
221
	int idx;
222

  
223
	idx = EXTRACT_FIELD(sel, 0, 4);
224
	set = EXTRACT_FIELD(sel, 4, 5);
225

  
226
	hi = env->tlbsets[1][set][idx].hi;
227
	vaddr = EXTRACT_FIELD(hi, 13, 31);
228
	return vaddr << TARGET_PAGE_BITS;
229
}
230

  
112 231
int cris_mmu_translate(struct cris_mmu_result_t *res,
113 232
		       CPUState *env, uint32_t vaddr,
114 233
		       int rw, int mmu_idx)
......
116 235
	uint32_t phy = vaddr;
117 236
	int seg;
118 237
	int miss = 0;
119
        int is_user = mmu_idx == MMU_USER_IDX;
238
	int is_user = mmu_idx == MMU_USER_IDX;
120 239

  
121 240
	if (!cris_mmu_enabled(env->sregs[SFR_RW_GC_CFG])) {
122 241
		res->phy = vaddr;
......
142 261
			res->phy = phy;
143 262
		}
144 263
	}
145
//	printf ("miss=%d v=%x -> p=%x\n", miss, vaddr, phy);
264
	D(printf ("miss=%d v=%x -> p=%x\n", miss, vaddr, phy));
146 265
	return miss;
147 266
}
148 267
#endif
b/target-cris/mmu.h
7 7
{
8 8
	uint32_t phy;
9 9
	uint32_t pfn;
10
	int g:1;
11
	int v:1;
12
	int k:1;
13
	int w:1;
14
	int e:1;
15
	int cause_op;
10
	int bf_vec;
16 11
};
17 12

  
13
target_ulong cris_mmu_tlb_latest_update(CPUState *env, uint32_t new_lo);
18 14
int cris_mmu_translate(struct cris_mmu_result_t *res,
19 15
		       CPUState *env, uint32_t vaddr,
20 16
		       int rw, int mmu_idx);
b/target-cris/op.c
153 153

  
154 154
void OPPROTO op_break_im(void)
155 155
{
156
	env->trapnr = PARAM1;
156
	env->trap_vector = PARAM1;
157 157
	env->exception_index = EXCP_BREAK;
158 158
	cpu_loop_exit();
159 159
}
......
196 196

  
197 197
	/* Apply the ccs shift.  */
198 198
	ccs = env->pregs[PR_CCS];
199
	ccs = (ccs & 0xc0000000) | (ccs >> 10);
199
	ccs = (ccs & 0xc0000000) | ((ccs & 0x0fffffff) >> 10);
200 200
	env->pregs[PR_CCS] = ccs;
201 201
	RETURN();
202 202
}
......
269 269
	RETURN();
270 270
}
271 271

  
272
void OPPROTO op_movl_tlb_hi_T0 (void)
273
{
274
	uint32_t srs;
275
	srs = env->pregs[PR_SRS];
276
	if (srs == 1 || srs == 2)
277
	{
278
		/* Writes to tlb-hi write to mm_cause as a side effect.  */
279
		env->sregs[SFR_RW_MM_TLB_HI] = T0;
280
		env->sregs[SFR_R_MM_CAUSE] = T0;
281
	}
282
	RETURN();
283
}
284

  
272 285
void OPPROTO op_movl_tlb_lo_T0 (void)
273 286
{
274
	int srs;
287
	uint32_t srs;
275 288
	srs = env->pregs[PR_SRS];
276 289
	if (srs == 1 || srs == 2)
277 290
	{
278
		int set;
279
		int idx;
291
		uint32_t set;
292
		uint32_t idx;
280 293
		uint32_t lo, hi;
281 294

  
282 295
		idx = set = env->sregs[SFR_RW_MM_TLB_SEL];
283 296
		set >>= 4;
284 297
		set &= 3;
285 298

  
286
		idx &= 31;
299
		idx &= 15;
287 300
		/* We've just made a write to tlb_lo.  */
288 301
		lo = env->sregs[SFR_RW_MM_TLB_LO];
289
		hi = env->sregs[SFR_RW_MM_TLB_HI];
302
		/* Writes are done via r_mm_cause.  */
303
		hi = env->sregs[SFR_R_MM_CAUSE];
290 304
		env->tlbsets[srs - 1][set][idx].lo = lo;
291 305
		env->tlbsets[srs - 1][set][idx].hi = hi;
292 306
	}
293

  
294 307
	RETURN();
295 308
}
296 309

  
b/target-cris/op_helper.c
21 21

  
22 22
#include <assert.h>
23 23
#include "exec.h"
24
#include "mmu.h"
24 25

  
25 26
#define MMUSUFFIX _mmu
26 27
#ifdef __s390__
......
41 42
#define SHIFT 3
42 43
#include "softmmu_template.h"
43 44

  
45
#define D(x)
46

  
44 47
/* Try to fill the TLB and return an exception if error. If retaddr is
45 48
   NULL, it means that the function was called in C code (i.e. not
46 49
   from generated code or from helper.c) */
......
73 76
    env = saved_env;
74 77
}
75 78

  
79
void helper_tlb_update(uint32_t T0)
80
{
81
#if !defined(CONFIG_USER_ONLY)
82
	uint32_t vaddr;
83

  
84
	vaddr = cris_mmu_tlb_latest_update(env, T0);
85
	D(printf("flush vaddr %x\n", vaddr));
86
	tlb_flush_page(env, vaddr);
87
#endif
88
}
89

  
76 90
void do_unassigned_access(target_phys_addr_t addr, int is_write, int is_exec,
77 91
                          int is_asi)
78 92
{
79

  
93
	D(printf("%s addr=%x w=%d ex=%d asi=%d\n", 
94
		__func__, addr, is_write, is_exec, is_asi));
80 95
}

Also available in: Unified diff