/[dynamips]/upstream/dynamips-0.2.6-RC3/mips_mts.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/dynamips-0.2.6-RC3/mips_mts.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4 - (show annotations)
Sat Oct 6 16:06:49 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 22470 byte(s)
dynamips-0.2.6-RC3

1 /*
2 * Cisco router simulation platform.
3 * Copyright (c) 2005,2006 Christophe Fillot (cf@utc.fr)
4 *
5 * Template code for MTS.
6 */
7
8 #define MTS_ENTRY MTS_PROTO(entry_t)
9 #define MTS_CHUNK MTS_PROTO(chunk_t)
10
11 /* Forward declarations */
12 static forced_inline void *MTS_PROTO(access)(cpu_mips_t *cpu,m_uint64_t vaddr,
13 u_int op_code,u_int op_size,
14 u_int op_type,m_uint64_t *data,
15 u_int *exc);
16
17 static fastcall int MTS_PROTO(translate)(cpu_mips_t *cpu,m_uint64_t vaddr,
18 m_uint32_t *phys_page);
19
20 /* Initialize the MTS subsystem for the specified CPU */
21 int MTS_PROTO(init)(cpu_mips_t *cpu)
22 {
23 size_t len;
24
25 /* Initialize the cache entries to 0 (empty) */
26 len = MTS_PROTO_UP(HASH_SIZE) * sizeof(MTS_ENTRY *);
27 if (!(cpu->mts_cache = malloc(len)))
28 return(-1);
29
30 memset(cpu->mts_cache,0,len);
31 cpu->mts_lookups = 0;
32 cpu->mts_misses = 0;
33
34 /* Reset the TLB reverse map (used for selective invalidations) */
35 memset(cpu->mts_rmap,0,(cpu->cp0.tlb_entries * sizeof(MTS_ENTRY *)));
36 return(0);
37 }
38
39 /* Free memory used by MTS */
40 void MTS_PROTO(shutdown)(cpu_mips_t *cpu)
41 {
42 MTS_CHUNK *chunk,*next;
43 int i;
44
45 /* Reset the reverse map */
46 for(i=0;i<cpu->cp0.tlb_entries;i++)
47 cpu->mts_rmap[i] = NULL;
48
49 /* Free the cache itself */
50 free(cpu->mts_cache);
51 cpu->mts_cache = NULL;
52
53 /* Free the chunks */
54 for(chunk=cpu->mts_chunk_list;chunk;chunk=next) {
55 next = chunk->next;
56 free(chunk);
57 }
58
59 for(chunk=cpu->mts_chunk_free_list;chunk;chunk=next) {
60 next = chunk->next;
61 free(chunk);
62 }
63
64 cpu->mts_chunk_list = cpu->mts_chunk_free_list = NULL;
65 cpu->mts_entry_free_list = NULL;
66 }
67
68 /* Show MTS detailed information (debugging only!) */
69 void MTS_PROTO(show_stats)(cpu_mips_t *cpu)
70 {
71 MTS_CHUNK *chunk;
72 #if DEBUG_MTS_MAP_VIRT
73 MTS_ENTRY *entry;
74 u_int i;
75 #endif
76 u_int count;
77
78 printf("\nCPU%u: MTS%d statistics:\n",cpu->id,MTS_ADDR_SIZE);
79
80 printf(" Total lookups: %llu, misses: %llu, efficiency: %g%%\n",
81 cpu->mts_lookups, cpu->mts_misses,
82 100 - ((double)(cpu->mts_misses*100)/
83 (double)cpu->mts_lookups));
84
85 #if DEBUG_MTS_MAP_VIRT
86 /* Valid hash entries */
87 for(count=0,i=0;i<MTS_PROTO_UP(HASH_SIZE);i++) {
88 if ((entry = cpu->mts_cache[i]) != NULL) {
89 printf(" %4u: entry=%p, start=0x%16.16llx, "
90 "len=0x%8.8x, action=0x%8.8llx\n",
91 i,entry,(m_uint64_t)entry->start,entry->mask,
92 (m_uint64_t)entry->action);
93 count++;
94 }
95 }
96
97 printf(" %u/%u valid hash entries.\n",count,MTS_PROTO_UP(HASH_SIZE));
98 #endif
99
100 /* Number of chunks */
101 for(count=0,chunk=cpu->mts_chunk_list;chunk;chunk=chunk->next)
102 count++;
103
104 printf(" Number of chunks: %u\n",count);
105
106 #if DEBUG_MTS_MAP_VIRT
107 /* Reverse map */
108 for(i=0;i<MIPS64_TLB_MAX_ENTRIES;i++) {
109 for(count=0,entry=cpu->mts_rmap[i];entry;entry=entry->next)
110 count++;
111
112 if (count > 0)
113 printf(" tlb_rmap[%u]: %u entries\n",i,count);
114 }
115 #endif
116 }
117
118 /* Allocate a new chunk */
119 static int MTS_PROTO(alloc_chunk)(cpu_mips_t *cpu)
120 {
121 MTS_CHUNK *chunk;
122
123 /* Try the free list first, then use standard allocation procedure */
124 if ((chunk = cpu->mts_chunk_free_list) != NULL) {
125 cpu->mts_chunk_free_list = chunk->next;
126 } else {
127 if (!(chunk = malloc(sizeof(*chunk))))
128 return(-1);
129 }
130
131 chunk->count = 0;
132 chunk->next = cpu->mts_chunk_list;
133 cpu->mts_chunk_list = chunk;
134 return(0);
135 }
136
137 /* Allocate a new entry */
138 static MTS_ENTRY *MTS_PROTO(alloc_entry)(cpu_mips_t *cpu)
139 {
140 MTS_CHUNK *chunk = cpu->mts_chunk_list;
141 MTS_ENTRY *entry;
142
143 /* First, try to allocate the entry from the free list */
144 if ((entry = cpu->mts_entry_free_list) != NULL) {
145 cpu->mts_entry_free_list = ((MTS_ENTRY *)cpu->mts_entry_free_list)->next;
146 return entry;
147 }
148
149 /* A new chunk is required */
150 if (!chunk || (chunk->count == MTS_PROTO_UP(CHUNK_SIZE))) {
151 if (MTS_PROTO(alloc_chunk)(cpu) == -1)
152 return NULL;
153
154 chunk = cpu->mts_chunk_list;
155 }
156
157 entry = &chunk->entry[chunk->count];
158 chunk->count++;
159 return entry;
160 }
161
162 /* Invalidate the complete MTS cache */
163 void MTS_PROTO(invalidate_cache)(cpu_mips_t *cpu)
164 {
165 MTS_CHUNK *chunk;
166 size_t len;
167 u_int i;
168
169 len = MTS_PROTO_UP(HASH_SIZE) * sizeof(MTS_ENTRY *);
170 memset(cpu->mts_cache,0,len);
171
172 /* Move all chunks to the free list */
173 while((chunk = cpu->mts_chunk_list) != NULL) {
174 cpu->mts_chunk_list = chunk->next;
175 chunk->next = cpu->mts_chunk_free_list;
176 cpu->mts_chunk_free_list = chunk;
177 }
178
179 /* Reset the free list of entries (since they are located in chunks) */
180 cpu->mts_entry_free_list = NULL;
181
182 /* Reset the reverse map */
183 for(i=0;i<cpu->cp0.tlb_entries;i++)
184 cpu->mts_rmap[i] = NULL;
185 }
186
187 /* Invalidate partially the MTS cache, given a TLB entry index */
188 void MTS_PROTO(invalidate_tlb_entry)(cpu_mips_t *cpu,u_int tlb_index)
189 {
190 MTS_ENTRY *entry;
191
192 for(entry=cpu->mts_rmap[tlb_index];entry;entry=entry->next) {
193 *(entry->pself) = NULL;
194 if (!entry->next) {
195 entry->next = cpu->mts_entry_free_list;
196 break;
197 }
198 }
199
200 cpu->mts_entry_free_list = cpu->mts_rmap[tlb_index];
201 cpu->mts_rmap[tlb_index] = NULL;
202 }
203
204 /*
205 * MTS mapping.
206 *
207 * It is NOT inlined since it triggers a GCC bug on my config (x86, GCC 3.3.5)
208 */
209 static no_inline int MTS_PROTO(map)(cpu_mips_t *cpu,m_uint64_t vaddr,
210 mts_map_t *map,MTS_ENTRY *entry)
211 {
212 struct vdevice *dev;
213 m_uint64_t lk_addr;
214 m_uint32_t poffset;
215
216 lk_addr = map->paddr + (vaddr - map->vaddr);
217
218 if (!(dev = dev_lookup(cpu->vm,lk_addr,map->cached)))
219 return(FALSE);
220
221 if (map->paddr > dev->phys_addr) {
222 poffset = map->paddr - dev->phys_addr;
223 entry->start = map->vaddr;
224 entry->phys_page = map->paddr >> MIPS_MIN_PAGE_SHIFT;
225 entry->mask = ~((m_min(map->len,dev->phys_len - poffset)) - 1);
226 entry->action = poffset;
227 } else {
228 poffset = dev->phys_addr - map->paddr;
229 entry->start = map->vaddr + poffset;
230 entry->phys_page = (map->paddr + poffset) >> MIPS_MIN_PAGE_SHIFT;
231 entry->mask = ~((m_min(map->len - poffset,dev->phys_len)) - 1);
232 entry->action = 0;
233 }
234
235 if (!dev->host_addr || (dev->flags & VDEVICE_FLAG_NO_MTS_MMAP))
236 entry->action += (dev->id << MTS_DEVID_SHIFT) | MTS_DEV_MASK;
237 else
238 entry->action += dev->host_addr;
239
240 return(TRUE);
241 }
242
243 /* MTS lookup */
244 static void *MTS_PROTO(lookup)(cpu_mips_t *cpu,m_uint64_t vaddr)
245 {
246 m_uint64_t data;
247 u_int exc;
248 return(MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_LOOKUP,4,MTS_READ,
249 &data,&exc));
250 }
251
252 /* === MIPS Memory Operations ============================================= */
253
254 /* LB: Load Byte */
255 fastcall u_int MTS_PROTO(lb)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
256 {
257 m_uint64_t data;
258 void *haddr;
259 u_int exc;
260
261 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_LB,1,MTS_READ,&data,&exc);
262 if (likely(haddr != NULL)) data = *(m_uint8_t *)haddr;
263 if (likely(!exc)) cpu->gpr[reg] = sign_extend(data,8);
264 return(exc);
265 }
266
267 /* LBU: Load Byte Unsigned */
268 fastcall u_int MTS_PROTO(lbu)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
269 {
270 m_uint64_t data;
271 void *haddr;
272 u_int exc;
273
274 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_LBU,1,MTS_READ,&data,&exc);
275 if (likely(haddr != NULL)) data = *(m_uint8_t *)haddr;
276 if (likely(!exc)) cpu->gpr[reg] = data & 0xff;
277 return(exc);
278 }
279
280 /* LH: Load Half-Word */
281 fastcall u_int MTS_PROTO(lh)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
282 {
283 m_uint64_t data;
284 void *haddr;
285 u_int exc;
286
287 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_LH,2,MTS_READ,&data,&exc);
288 if (likely(haddr != NULL)) data = vmtoh16(*(m_uint16_t *)haddr);
289 if (likely(!exc)) cpu->gpr[reg] = sign_extend(data,16);
290 return(exc);
291 }
292
293 /* LHU: Load Half-Word Unsigned */
294 fastcall u_int MTS_PROTO(lhu)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
295 {
296 m_uint64_t data;
297 void *haddr;
298 u_int exc;
299
300 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_LHU,2,MTS_READ,&data,&exc);
301 if (likely(haddr != NULL)) data = vmtoh16(*(m_uint16_t *)haddr);
302 if (likely(!exc)) cpu->gpr[reg] = data & 0xffff;
303 return(exc);
304 }
305
306 /* LW: Load Word */
307 fastcall u_int MTS_PROTO(lw)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
308 {
309 m_uint64_t data;
310 void *haddr;
311 u_int exc;
312
313 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_LW,4,MTS_READ,&data,&exc);
314 if (likely(haddr != NULL)) data = vmtoh32(*(m_uint32_t *)haddr);
315 if (likely(!exc)) cpu->gpr[reg] = sign_extend(data,32);
316 return(exc);
317 }
318
319 /* LWU: Load Word Unsigned */
320 fastcall u_int MTS_PROTO(lwu)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
321 {
322 m_uint64_t data;
323 void *haddr;
324 u_int exc;
325
326 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_LWU,4,MTS_READ,&data,&exc);
327 if (likely(haddr != NULL)) data = vmtoh32(*(m_uint32_t *)haddr);
328 if (likely(!exc)) cpu->gpr[reg] = data & 0xffffffff;
329 return(exc);
330 }
331
332 /* LD: Load Double-Word */
333 fastcall u_int MTS_PROTO(ld)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
334 {
335 m_uint64_t data;
336 void *haddr;
337 u_int exc;
338
339 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_LD,8,MTS_READ,&data,&exc);
340 if (likely(haddr != NULL)) data = vmtoh64(*(m_uint64_t *)haddr);
341 if (likely(!exc)) cpu->gpr[reg] = data;
342 return(exc);
343 }
344
345 /* SB: Store Byte */
346 fastcall u_int MTS_PROTO(sb)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
347 {
348 m_uint64_t data;
349 void *haddr;
350 u_int exc;
351
352 data = cpu->gpr[reg] & 0xff;
353 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_SB,1,MTS_WRITE,&data,&exc);
354 if (likely(haddr != NULL)) *(m_uint8_t *)haddr = data;
355 return(exc);
356 }
357
358 /* SH: Store Half-Word */
359 fastcall u_int MTS_PROTO(sh)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
360 {
361 m_uint64_t data;
362 void *haddr;
363 u_int exc;
364
365 data = cpu->gpr[reg] & 0xffff;
366 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_SH,2,MTS_WRITE,&data,&exc);
367 if (likely(haddr != NULL)) *(m_uint16_t *)haddr = htovm16(data);
368 return(exc);
369 }
370
371 /* SW: Store Word */
372 fastcall u_int MTS_PROTO(sw)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
373 {
374 m_uint64_t data;
375 void *haddr;
376 u_int exc;
377
378 data = cpu->gpr[reg] & 0xffffffff;
379 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_SW,4,MTS_WRITE,&data,&exc);
380 if (likely(haddr != NULL)) *(m_uint32_t *)haddr = htovm32(data);
381 return(exc);
382 }
383
384 /* SD: Store Double-Word */
385 fastcall u_int MTS_PROTO(sd)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
386 {
387 m_uint64_t data;
388 void *haddr;
389 u_int exc;
390
391 data = cpu->gpr[reg];
392 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_SD,8,MTS_WRITE,&data,&exc);
393 if (likely(haddr != NULL)) *(m_uint64_t *)haddr = htovm64(data);
394 return(exc);
395 }
396
397 /* LDC1: Load Double-Word To Coprocessor 1 */
398 fastcall u_int MTS_PROTO(ldc1)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
399 {
400 m_uint64_t data;
401 void *haddr;
402 u_int exc;
403
404 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_LDC1,8,MTS_READ,&data,&exc);
405 if (likely(haddr != NULL)) data = vmtoh64(*(m_uint64_t *)haddr);
406 if (likely(!exc)) cpu->fpu.reg[reg] = data;
407 return(exc);
408 }
409
410 /* LWL: Load Word Left */
411 fastcall u_int MTS_PROTO(lwl)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
412 {
413 m_uint64_t r_mask,naddr;
414 m_uint64_t data;
415 u_int m_shift;
416 void *haddr;
417 u_int exc;
418
419 naddr = vaddr & ~(0x03);
420 haddr = MTS_PROTO(access)(cpu,naddr,MIPS_MEMOP_LWL,4,MTS_READ,&data,&exc);
421
422 if (likely(haddr != NULL))
423 data = vmtoh32(*(m_uint32_t *)haddr);
424
425 if (likely(!exc)) {
426 m_shift = (vaddr & 0x03) << 3;
427 r_mask = (1ULL << m_shift) - 1;
428 data <<= m_shift;
429
430 cpu->gpr[reg] &= r_mask;
431 cpu->gpr[reg] |= data;
432 cpu->gpr[reg] = sign_extend(cpu->gpr[reg],32);
433 }
434 return(exc);
435 }
436
437 /* LWR: Load Word Right */
438 fastcall u_int MTS_PROTO(lwr)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
439 {
440 m_uint64_t r_mask,naddr;
441 m_uint64_t data;
442 u_int m_shift;
443 void *haddr;
444 u_int exc;
445
446 naddr = vaddr & ~(0x03);
447 haddr = MTS_PROTO(access)(cpu,naddr,MIPS_MEMOP_LWR,4,MTS_READ,&data,&exc);
448
449 if (likely(haddr != NULL))
450 data = vmtoh32(*(m_uint32_t *)haddr);
451
452 if (likely(!exc)) {
453 m_shift = ((vaddr & 0x03) + 1) << 3;
454 r_mask = (1ULL << m_shift) - 1;
455
456 data = sign_extend(data >> (32 - m_shift),32);
457 r_mask = sign_extend(r_mask,32);
458
459 cpu->gpr[reg] &= ~r_mask;
460 cpu->gpr[reg] |= data;
461 }
462 return(exc);
463 }
464
465 /* LDL: Load Double-Word Left */
466 fastcall u_int MTS_PROTO(ldl)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
467 {
468 m_uint64_t r_mask,naddr;
469 m_uint64_t data;
470 u_int m_shift;
471 void *haddr;
472 u_int exc;
473
474 naddr = vaddr & ~(0x07);
475 haddr = MTS_PROTO(access)(cpu,naddr,MIPS_MEMOP_LDL,8,MTS_READ,&data,&exc);
476
477 if (likely(haddr != NULL))
478 data = vmtoh64(*(m_uint64_t *)haddr);
479
480 if (likely(!exc)) {
481 m_shift = (vaddr & 0x07) << 3;
482 r_mask = (1ULL << m_shift) - 1;
483 data <<= m_shift;
484
485 cpu->gpr[reg] &= r_mask;
486 cpu->gpr[reg] |= data;
487 }
488 return(exc);
489 }
490
491 /* LDR: Load Double-Word Right */
492 fastcall u_int MTS_PROTO(ldr)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
493 {
494 m_uint64_t r_mask,naddr;
495 m_uint64_t data;
496 u_int m_shift;
497 void *haddr;
498 u_int exc;
499
500 naddr = vaddr & ~(0x07);
501 haddr = MTS_PROTO(access)(cpu,naddr,MIPS_MEMOP_LDR,8,MTS_READ,&data,&exc);
502
503 if (likely(haddr != NULL))
504 data = vmtoh64(*(m_uint64_t *)haddr);
505
506 if (likely(!exc)) {
507 m_shift = ((vaddr & 0x07) + 1) << 3;
508 r_mask = (1ULL << m_shift) - 1;
509 data >>= (64 - m_shift);
510
511 cpu->gpr[reg] &= ~r_mask;
512 cpu->gpr[reg] |= data;
513 }
514 return(exc);
515 }
516
517 /* SWL: Store Word Left */
518 fastcall u_int MTS_PROTO(swl)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
519 {
520 m_uint64_t d_mask,naddr;
521 m_uint64_t data;
522 u_int r_shift;
523 void *haddr;
524 u_int exc;
525
526 naddr = vaddr & ~(0x03ULL);
527 haddr = MTS_PROTO(access)(cpu,naddr,MIPS_MEMOP_SWL,4,MTS_READ,&data,&exc);
528 if (unlikely(exc)) return(exc);
529
530 if (likely(haddr != NULL))
531 data = vmtoh32(*(m_uint32_t *)haddr);
532
533 r_shift = (vaddr & 0x03) << 3;
534 d_mask = 0xffffffff >> r_shift;
535
536 data &= ~d_mask;
537 data |= (cpu->gpr[reg] & 0xffffffff) >> r_shift;
538
539 haddr = MTS_PROTO(access)(cpu,naddr,MIPS_MEMOP_SWL,4,MTS_WRITE,&data,&exc);
540 if (likely(haddr != NULL)) *(m_uint32_t *)haddr = htovm32(data);
541 return(exc);
542 }
543
544 /* SWR: Store Word Right */
545 fastcall u_int MTS_PROTO(swr)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
546 {
547 m_uint64_t d_mask,naddr;
548 m_uint64_t data;
549 u_int r_shift;
550 void *haddr;
551 u_int exc;
552
553 naddr = vaddr & ~(0x03);
554 haddr = MTS_PROTO(access)(cpu,naddr,MIPS_MEMOP_SWR,4,MTS_READ,&data,&exc);
555 if (unlikely(exc)) return(exc);
556
557 if (likely(haddr != NULL))
558 data = vmtoh32(*(m_uint32_t *)haddr);
559
560 r_shift = ((vaddr & 0x03) + 1) << 3;
561 d_mask = 0xffffffff >> r_shift;
562
563 data &= d_mask;
564 data |= (cpu->gpr[reg] << (32 - r_shift)) & 0xffffffff;
565
566 haddr = MTS_PROTO(access)(cpu,naddr,MIPS_MEMOP_SWR,4,MTS_WRITE,&data,&exc);
567 if (likely(haddr != NULL)) *(m_uint32_t *)haddr = htovm32(data);
568 return(exc);
569 }
570
571 /* SDL: Store Double-Word Left */
572 fastcall u_int MTS_PROTO(sdl)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
573 {
574 m_uint64_t d_mask,naddr;
575 m_uint64_t data;
576 u_int r_shift;
577 void *haddr;
578 u_int exc;
579
580 naddr = vaddr & ~(0x07);
581 haddr = MTS_PROTO(access)(cpu,naddr,MIPS_MEMOP_SDL,8,MTS_READ,&data,&exc);
582 if (unlikely(exc)) return(exc);
583
584 if (likely(haddr != NULL))
585 data = vmtoh64(*(m_uint64_t *)haddr);
586
587 r_shift = (vaddr & 0x07) << 3;
588 d_mask = 0xffffffffffffffffULL >> r_shift;
589
590 data &= ~d_mask;
591 data |= cpu->gpr[reg] >> r_shift;
592
593 haddr = MTS_PROTO(access)(cpu,naddr,MIPS_MEMOP_SDL,8,MTS_WRITE,&data,&exc);
594 if (likely(haddr != NULL)) *(m_uint64_t *)haddr = htovm64(data);
595 return(exc);
596 }
597
598 /* SDR: Store Double-Word Right */
599 fastcall u_int MTS_PROTO(sdr)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
600 {
601 m_uint64_t d_mask,naddr;
602 m_uint64_t data;
603 u_int r_shift;
604 void *haddr;
605 u_int exc;
606
607 naddr = vaddr & ~(0x07);
608 haddr = MTS_PROTO(access)(cpu,naddr,MIPS_MEMOP_SDR,8,MTS_READ,&data,&exc);
609 if (unlikely(exc)) return(exc);
610
611 if (likely(haddr != NULL))
612 data = vmtoh64(*(m_uint64_t *)haddr);
613
614 r_shift = ((vaddr & 0x07) + 1) << 3;
615 d_mask = 0xffffffffffffffffULL >> r_shift;
616
617 data &= d_mask;
618 data |= cpu->gpr[reg] << (64 - r_shift);
619
620 haddr = MTS_PROTO(access)(cpu,naddr,MIPS_MEMOP_SDR,8,MTS_WRITE,&data,&exc);
621 if (likely(haddr != NULL)) *(m_uint64_t *)haddr = htovm64(data);
622 return(exc);
623 }
624
625 /* LL: Load Linked */
626 fastcall u_int MTS_PROTO(ll)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
627 {
628 m_uint64_t data;
629 void *haddr;
630 u_int exc;
631
632 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_LL,4,MTS_READ,&data,&exc);
633 if (likely(haddr != NULL)) data = vmtoh32(*(m_uint32_t *)haddr);
634
635 if (likely(!exc)) {
636 cpu->gpr[reg] = sign_extend(data,32);
637 cpu->ll_bit = 1;
638 }
639
640 return(exc);
641 }
642
643 /* SC: Store Conditional */
644 fastcall u_int MTS_PROTO(sc)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
645 {
646 m_uint64_t data;
647 void *haddr;
648 u_int exc = 0;
649
650 if (cpu->ll_bit) {
651 data = cpu->gpr[reg] & 0xffffffff;
652 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_SC,4,MTS_WRITE,
653 &data,&exc);
654 if (likely(haddr != NULL)) *(m_uint32_t *)haddr = htovm32(data);
655 }
656
657 if (likely(!exc))
658 cpu->gpr[reg] = cpu->ll_bit;
659 return(exc);
660 }
661
662 /* SDC1: Store Double-Word from Coprocessor 1 */
663 fastcall u_int MTS_PROTO(sdc1)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int reg)
664 {
665 m_uint64_t data;
666 void *haddr;
667 u_int exc;
668
669 data = cpu->fpu.reg[reg];
670 haddr = MTS_PROTO(access)(cpu,vaddr,MIPS_MEMOP_SDC1,8,MTS_WRITE,
671 &data,&exc);
672 if (likely(haddr != NULL)) *(m_uint64_t *)haddr = htovm64(data);
673 return(exc);
674 }
675
676 /* CACHE: Cache operation */
677 fastcall u_int MTS_PROTO(cache)(cpu_mips_t *cpu,m_uint64_t vaddr,u_int op)
678 {
679 struct insn_block *block;
680 m_uint32_t phys_page;
681
682 #if DEBUG_CACHE
683 cpu_log(cpu,"MTS","CACHE: PC=0x%llx, vaddr=0x%llx, cache=%u, code=%u\n",
684 cpu->pc, vaddr, op & 0x3, op >> 2);
685 #endif
686
687 if (!cpu->translate(cpu,vaddr,&phys_page)) {
688 if ((phys_page < 1048576) && cpu->exec_phys_map) {
689 block = cpu->exec_phys_map[phys_page];
690
691 if (block) {
692 if ((cpu->pc < block->start_pc) ||
693 ((cpu->pc - block->start_pc) >= MIPS_MIN_PAGE_SIZE))
694 {
695 #if DEBUG_CACHE
696 cpu_log(cpu,"MTS",
697 "CACHE: removing compiled page at 0x%llx, pc=0x%llx\n",
698 block->start_pc,cpu->pc);
699 #endif
700 cpu->exec_phys_map[phys_page] = NULL;
701 insn_block_free(cpu,block,TRUE);
702 }
703 else
704 {
705 #if DEBUG_CACHE
706 cpu_log(cpu,"MTS",
707 "CACHE: trying to remove page 0x%llx with pc=0x%llx\n",
708 block->start_pc,cpu->pc);
709 #endif
710 }
711 }
712 }
713 }
714
715 return(0);
716 }
717
718 /* === MTS Cache Management ============================================= */
719
720 /* MTS map/unmap/rebuild "API" functions */
721 void MTS_PROTO(api_map)(cpu_mips_t *cpu,m_uint64_t vaddr,m_uint64_t paddr,
722 m_uint32_t len,int cache_access,int tlb_index)
723 {
724 /* nothing to do, the cache will be filled on-the-fly */
725 }
726
727 void MTS_PROTO(api_unmap)(cpu_mips_t *cpu,m_uint64_t vaddr,m_uint32_t len,
728 m_uint32_t val,int tlb_index)
729 {
730 /* Invalidate the TLB entry or the full cache if no index is specified */
731 if (tlb_index != -1)
732 MTS_PROTO(invalidate_tlb_entry)(cpu,tlb_index);
733 else
734 MTS_PROTO(invalidate_cache)(cpu);
735 }
736
737 void MTS_PROTO(api_rebuild)(cpu_mips_t *cpu)
738 {
739 MTS_PROTO(invalidate_cache)(cpu);
740 }
741
742 /* ======================================================================== */
743
744 /* Initialize memory access vectors */
745 void MTS_PROTO(init_memop_vectors)(cpu_mips_t *cpu)
746 {
747 /* XXX TODO:
748 * - LD/SD forbidden in Supervisor/User modes with 32-bit addresses.
749 */
750
751 cpu->addr_mode = MTS_ADDR_SIZE;
752
753 /* API vectors */
754 cpu->mts_map = MTS_PROTO(api_map);
755 cpu->mts_unmap = MTS_PROTO(api_unmap);
756 cpu->mts_rebuild = MTS_PROTO(api_rebuild);
757
758 /* memory lookup operation */
759 cpu->mem_op_lookup = MTS_PROTO(lookup);
760
761 /* Translation operation */
762 cpu->translate = MTS_PROTO(translate);
763
764 /* Shutdown operation */
765 cpu->mts_shutdown = MTS_PROTO(shutdown);
766
767 /* Show statistics */
768 cpu->mts_show_stats = MTS_PROTO(show_stats);
769
770 /* Load Operations */
771 cpu->mem_op_fn[MIPS_MEMOP_LB] = MTS_PROTO(lb);
772 cpu->mem_op_fn[MIPS_MEMOP_LBU] = MTS_PROTO(lbu);
773 cpu->mem_op_fn[MIPS_MEMOP_LH] = MTS_PROTO(lh);
774 cpu->mem_op_fn[MIPS_MEMOP_LHU] = MTS_PROTO(lhu);
775 cpu->mem_op_fn[MIPS_MEMOP_LW] = MTS_PROTO(lw);
776 cpu->mem_op_fn[MIPS_MEMOP_LWU] = MTS_PROTO(lwu);
777 cpu->mem_op_fn[MIPS_MEMOP_LD] = MTS_PROTO(ld);
778 cpu->mem_op_fn[MIPS_MEMOP_LDL] = MTS_PROTO(ldl);
779 cpu->mem_op_fn[MIPS_MEMOP_LDR] = MTS_PROTO(ldr);
780
781 /* Store Operations */
782 cpu->mem_op_fn[MIPS_MEMOP_SB] = MTS_PROTO(sb);
783 cpu->mem_op_fn[MIPS_MEMOP_SH] = MTS_PROTO(sh);
784 cpu->mem_op_fn[MIPS_MEMOP_SW] = MTS_PROTO(sw);
785 cpu->mem_op_fn[MIPS_MEMOP_SD] = MTS_PROTO(sd);
786
787 /* Load Left/Right operations */
788 cpu->mem_op_fn[MIPS_MEMOP_LWL] = MTS_PROTO(lwl);
789 cpu->mem_op_fn[MIPS_MEMOP_LWR] = MTS_PROTO(lwr);
790 cpu->mem_op_fn[MIPS_MEMOP_LDL] = MTS_PROTO(ldl);
791 cpu->mem_op_fn[MIPS_MEMOP_LDR] = MTS_PROTO(ldr);
792
793 /* Store Left/Right operations */
794 cpu->mem_op_fn[MIPS_MEMOP_SWL] = MTS_PROTO(swl);
795 cpu->mem_op_fn[MIPS_MEMOP_SWR] = MTS_PROTO(swr);
796 cpu->mem_op_fn[MIPS_MEMOP_SDL] = MTS_PROTO(sdl);
797 cpu->mem_op_fn[MIPS_MEMOP_SDR] = MTS_PROTO(sdr);
798
799 /* LL/SC - Load Linked / Store Conditional */
800 cpu->mem_op_fn[MIPS_MEMOP_LL] = MTS_PROTO(ll);
801 cpu->mem_op_fn[MIPS_MEMOP_SC] = MTS_PROTO(sc);
802
803 /* Coprocessor 1 memory access functions */
804 cpu->mem_op_fn[MIPS_MEMOP_LDC1] = MTS_PROTO(ldc1);
805 cpu->mem_op_fn[MIPS_MEMOP_SDC1] = MTS_PROTO(sdc1);
806
807 /* Cache Operation */
808 cpu->mem_op_fn[MIPS_MEMOP_CACHE] = MTS_PROTO(cache);
809 }
810
811 #undef MTS_ADDR_SIZE
812 #undef MTS_PROTO
813 #undef MTS_PROTO_UP
814 #undef MTS_ENTRY
815 #undef MTS_CHUNK

  ViewVC Help
Powered by ViewVC 1.1.26