/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

1 dpavlin 4 /*
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