Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
8327 maxcodehac 1
#include "types.h"
2
#include "CPU.h"
3
#include "icache.h"
4
 
5
//#define ICACHE_DEBUGGING
6
 
7
 
8
 
9
#ifdef ICACHE_DEBUGGING
10
	#define _icache_fetch_func	icacheFetch_
11
	#define _icache_test_func	icacheFetch
12
#else
13
	#define _icache_fetch_func	icacheFetch
14
	#define _icache_test_func	icacheFetch_test
15
#endif
16
 
17
void icacheInval(icache* ic){
18
 
19
	UInt8 i, j;
20
 
21
	for(i = 0; i < ICACHE_BUCKET_NUM; i++){
22
		for(j = 0; j < ICACHE_BUCKET_SZ; j++) ic->lines[i][j].info = 0;
23
		ic->ptr[i] = 0;
24
	}
25
}
26
 
27
void icacheInit(icache* ic, ArmCpu* cpu, ArmCpuMemF memF){
28
 
29
	ic->cpu = cpu;
30
	ic->memF = memF;
31
 
32
	icacheInval(ic);
33
}
34
 
35
 
36
static UInt8 icachePrvHash(UInt32 addr){
37
 
38
	addr >>= ICACHE_L;
39
	addr &= (1UL << ICACHE_S) - 1UL;
40
 
41
	return addr;
42
}
43
 
44
void icacheInvalAddr(icache* ic, UInt32 va){
45
 
46
	UInt32 off = va % ICACHE_LINE_SZ;
47
	Int8 i, j, bucket;
48
	icacheLine* lines;
49
 
50
	va -= off;
51
 
52
	bucket = icachePrvHash(va);
53
	lines = ic->lines[bucket];
54
 
55
	for(i = 0, j = ic->ptr[bucket]; (UInt8)i < ICACHE_BUCKET_SZ; i++){
56
 
57
		if(--j == -1) j = ICACHE_BUCKET_SZ - 1;
58
 
59
		if((lines[j].info & (ICACHE_ADDR_MASK | ICACHE_USED_MASK)) == (va | ICACHE_USED_MASK)){	//found it!
60
 
61
			lines[j].info = 0;
62
		}
63
	}
64
}
65
 
66
/*
67
	we cannot have data overlap cachelines since data is self aligned (word on 4-byte boundary, halfwords on2, etc. this is enforced elsewhere
68
*/
69
 
70
Boolean _icache_fetch_func(icache* ic, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
71
 
72
	UInt32 off = va % ICACHE_LINE_SZ;
73
	Int8 i, j, bucket;
74
	icacheLine* lines;
75
	icacheLine* line;
76
 
77
	va -= off;
78
 
79
	bucket = icachePrvHash(va);
80
	lines = ic->lines[bucket];
81
 
82
	for(i = 0, j = ic->ptr[bucket]; (UInt8)i < ICACHE_BUCKET_SZ; i++){
83
 
84
		if(--j == -1) j = ICACHE_BUCKET_SZ - 1;
85
 
86
		if((lines[j].info & (ICACHE_ADDR_MASK | ICACHE_USED_MASK)) == (va | ICACHE_USED_MASK)){	//found it!
87
 
88
			if(sz == 4){
89
				*(UInt32*)buf = *(UInt32*)(lines[j].data + off);
90
			}
91
			else if(sz == 2){
92
				*(UInt16*)buf = *(UInt16*)(lines[j].data + off);
93
			}
94
			else __mem_copy(buf, lines[j].data + off, sz);
95
			return priviledged || !(lines[j].info & ICACHE_PRIV_MASK);
96
		}
97
	}
98
	//if we're here, we found nothing - time to populate the cache
99
	j = ic->ptr[bucket]++;
100
	if(ic->ptr[bucket] == ICACHE_BUCKET_SZ) ic->ptr[bucket] = 0;
101
	line = lines + j;
102
 
103
	line->info = va | (priviledged ? ICACHE_PRIV_MASK : 0);
104
	if(!ic->memF(ic->cpu, line->data, va, ICACHE_LINE_SZ, false, priviledged, fsrP)){
105
 
106
		return false;
107
	}
108
	line->info |= ICACHE_USED_MASK;
109
 
110
	if(sz == 4){
111
		*(UInt32*)buf = *(UInt32*)(line->data + off);
112
	}
113
	else if(sz == 2){
114
		*(UInt16*)buf = *(UInt16*)(line->data + off);
115
	}
116
	else __mem_copy(buf, line->data + off, sz);
117
	return true;
118
}
119
 
120
#include "stdio.h"
121
Boolean _icache_test_func(icache* ic, UInt32 va, UInt8 sz, Boolean priviledged, UInt8* fsrP, void* buf){
122
 
123
	UInt8 fsrO = -1, fsrT = -1;
124
	UInt8 dataO[4] = {0}, dataT[4] = {0};
125
	Boolean retO, retT;
126
	UInt8 i;
127
 
128
	retO = _icache_fetch_func(ic, va, sz, priviledged, &fsrO, dataO);
129
	retT = ic->memF(ic->cpu, dataT, va, sz, false, priviledged, &fsrT);
130
 
131
	if((retT != retO) || (fsrT != fsrO) || (dataT[0] != dataO[0]) || (dataT[1] != dataO[1]) || (dataT[2] != dataO[2]) || (dataT[3] != dataO[3])){
132
 
133
		fprintf(stderr, "icache fail!");
134
	}
135
 
136
	for(i = 0; i < sz; i++) ((UInt8*)buf)[i] = dataT[i];
137
	if(retT) *fsrP = fsrT;
138
	return retT;
139
}
140