1 |
14 |
hellwig |
/*
|
2 |
|
|
* main.c -- the main program
|
3 |
|
|
*/
|
4 |
|
|
|
5 |
|
|
|
6 |
|
|
#include "common.h"
|
7 |
|
|
#include "lib.h"
|
8 |
|
|
#include "start.h"
|
9 |
|
|
|
10 |
|
|
|
11 |
|
|
Word userMissTaken;
|
12 |
|
|
|
13 |
|
|
|
14 |
|
|
static InterruptContext initial = {
|
15 |
|
|
/* regs */
|
16 |
|
|
0x00000011, 0x11111112, 0x22222213, 0x33333314,
|
17 |
|
|
0x44444415, 0x55555516, 0x66666617, 0x77777718,
|
18 |
|
|
0x88888819, 0x9999991A, 0xAAAAAA1B, 0xBBBBBB1C,
|
19 |
|
|
0xCCCCCC1D, 0xDDDDDD1E, 0xEEEEEE1F, 0xFFFFFF10,
|
20 |
|
|
0x00000021, 0x11111122, 0x22222223, 0x33333324,
|
21 |
|
|
0x44444425, 0x55555526, 0x66666627, 0x77777728,
|
22 |
|
|
0x88888829, 0x9999992A, 0xAAAAAA2B, 0xBBBBBB2C,
|
23 |
|
|
0xCCCCCC2D, 0xDDDDDD2E, 0xEEEEEE2F, 0xFFFFFF20,
|
24 |
|
|
/* PSW */
|
25 |
|
|
0x03FF5678,
|
26 |
|
|
/* TLB index */
|
27 |
|
|
0x87654321,
|
28 |
|
|
/* TLB EntryHi */
|
29 |
|
|
0x9ABCDEF0,
|
30 |
|
|
/* TLB EntryLo */
|
31 |
|
|
0x0FEDCBA9
|
32 |
|
|
};
|
33 |
|
|
|
34 |
|
|
static InterruptContext ic;
|
35 |
|
|
|
36 |
|
|
|
37 |
|
|
static char *errorMessage[] = {
|
38 |
|
|
/* 0 */ "no error",
|
39 |
|
|
/* 1 */ "general register clobbered",
|
40 |
|
|
/* 2 */ "write to register 0 succeeded",
|
41 |
|
|
/* 3 */ "locus of exception incorrect",
|
42 |
|
|
/* 4 */ "TLB register clobbered",
|
43 |
|
|
/* 5 */ "vector bit incorrect",
|
44 |
|
|
/* 6 */ "user mode bits incorrect",
|
45 |
|
|
/* 7 */ "interrupt enable bits incorrect",
|
46 |
|
|
/* 8 */ "wrong exception number",
|
47 |
|
|
/* 9 */ "interrupt mask bits clobbered",
|
48 |
|
|
/* 10 */ "ISR entry was 'user miss'",
|
49 |
|
|
/* 11 */ "ISR entry was not 'user miss'",
|
50 |
|
|
};
|
51 |
|
|
|
52 |
|
|
|
53 |
|
|
static void flushTLB(void) {
|
54 |
|
|
Word invalPage;
|
55 |
|
|
int i;
|
56 |
|
|
|
57 |
|
|
invalPage = 0xC0000000;
|
58 |
|
|
for (i = 0; i < 32; i++) {
|
59 |
|
|
setTLB(i, invalPage, 0);
|
60 |
|
|
invalPage += (1 << 12);
|
61 |
|
|
}
|
62 |
|
|
}
|
63 |
|
|
|
64 |
|
|
|
65 |
|
|
static void check(unsigned int *res1, unsigned int *res2,
|
66 |
|
|
Word expectedEntryHi) {
|
67 |
|
|
int i;
|
68 |
|
|
|
69 |
|
|
*res1 = 0;
|
70 |
|
|
*res2 = 0;
|
71 |
|
|
for (i = 0; i < 32; i++) {
|
72 |
|
|
if (ic.reg[i] != initial.reg[i]) {
|
73 |
|
|
*res1 |= (1 << i);
|
74 |
|
|
}
|
75 |
|
|
}
|
76 |
|
|
if ((ic.psw & 0x0FFFFFFF) != (initial.psw & 0x0FFFFFFF)) {
|
77 |
|
|
*res2 |= (1 << 0);
|
78 |
|
|
}
|
79 |
|
|
if ((ic.tlbIndex & 0x0000001F) != (initial.tlbIndex & 0x0000001F)) {
|
80 |
|
|
*res2 |= (1 << 1);
|
81 |
|
|
}
|
82 |
|
|
if ((ic.tlbHi & 0xFFFFF000) != (expectedEntryHi & 0xFFFFF000)) {
|
83 |
|
|
*res2 |= (1 << 2);
|
84 |
|
|
}
|
85 |
|
|
if ((ic.tlbLo & 0x3FFFF003) != (initial.tlbLo & 0x3FFFF003)) {
|
86 |
|
|
*res2 |= (1 << 3);
|
87 |
|
|
}
|
88 |
|
|
}
|
89 |
|
|
|
90 |
|
|
|
91 |
|
|
static int execTest(void (*run)(InterruptContext *icp),
|
92 |
|
|
Word *expectedLocus,
|
93 |
|
|
int expectedException,
|
94 |
|
|
Bool execInUserMode,
|
95 |
|
|
Bool clobberEntryHi,
|
96 |
|
|
Bool shouldTakeUserMiss) {
|
97 |
|
|
unsigned int res1, res2;
|
98 |
|
|
int result;
|
99 |
|
|
Word *locus;
|
100 |
|
|
|
101 |
|
|
if (execInUserMode) {
|
102 |
|
|
initial.psw |= 1 << 26;
|
103 |
|
|
}
|
104 |
|
|
ic = initial;
|
105 |
|
|
flushTLB();
|
106 |
|
|
userMissTaken = 0xFFFFFFFF;
|
107 |
|
|
(*run)(&ic);
|
108 |
|
|
if (execInUserMode) {
|
109 |
|
|
locus = (Word *) (0xC0000000 | ic.reg[30]);
|
110 |
|
|
} else {
|
111 |
|
|
locus = (Word *) ic.reg[30];
|
112 |
|
|
}
|
113 |
|
|
if (!clobberEntryHi) {
|
114 |
|
|
check(&res1, &res2, initial.tlbHi);
|
115 |
|
|
} else {
|
116 |
|
|
if (shouldTakeUserMiss) {
|
117 |
|
|
check(&res1, &res2, initial.reg[3]);
|
118 |
|
|
} else {
|
119 |
|
|
check(&res1, &res2, initial.reg[11]);
|
120 |
|
|
}
|
121 |
|
|
}
|
122 |
|
|
result = 0;
|
123 |
|
|
if (((ic.psw >> 16) & 0x1F) != expectedException) {
|
124 |
|
|
result = 8;
|
125 |
|
|
} else
|
126 |
|
|
if (!shouldTakeUserMiss && userMissTaken != 0) {
|
127 |
|
|
result = 10;
|
128 |
|
|
} else
|
129 |
|
|
if (shouldTakeUserMiss && userMissTaken != (Word) &userMissTaken) {
|
130 |
|
|
result = 11;
|
131 |
|
|
} else
|
132 |
|
|
if (res1 != 0x50000001) {
|
133 |
|
|
result = 1;
|
134 |
|
|
} else
|
135 |
|
|
if (ic.reg[0] != 0x00000000) {
|
136 |
|
|
result = 2;
|
137 |
|
|
} else
|
138 |
|
|
if (locus != expectedLocus) {
|
139 |
|
|
result = 3;
|
140 |
|
|
} else
|
141 |
|
|
if (res2 != 0x00000001) {
|
142 |
|
|
result = 4;
|
143 |
|
|
} else
|
144 |
|
|
if (((ic.psw >> 27) & 0x01) != ((initial.psw >> 27) & 0x01)) {
|
145 |
|
|
result = 5;
|
146 |
|
|
} else
|
147 |
|
|
if (((ic.psw >> 24) & 0x07) != ((initial.psw >> 25) & 0x03)) {
|
148 |
|
|
result = 6;
|
149 |
|
|
} else
|
150 |
|
|
if (((ic.psw >> 21) & 0x07) != ((initial.psw >> 22) & 0x03)) {
|
151 |
|
|
result = 7;
|
152 |
|
|
} else
|
153 |
|
|
if (((ic.psw >> 0) & 0xFF) != ((initial.psw >> 0) & 0xFF)) {
|
154 |
|
|
result = 9;
|
155 |
|
|
}
|
156 |
|
|
if (execInUserMode) {
|
157 |
|
|
initial.psw &= ~(1 << 26);
|
158 |
|
|
}
|
159 |
|
|
return result;
|
160 |
|
|
}
|
161 |
|
|
|
162 |
|
|
|
163 |
|
|
static struct {
|
164 |
|
|
char *name;
|
165 |
|
|
void (*run)(InterruptContext *icp);
|
166 |
|
|
Word *locus;
|
167 |
|
|
int exception;
|
168 |
|
|
Bool execInUserMode;
|
169 |
|
|
Bool clobberEntryHi;
|
170 |
|
|
Bool shouldTakeUserMiss;
|
171 |
|
|
} tests[] = {
|
172 |
|
|
{ "Trap instr test:\t\t\t",
|
173 |
|
|
xtest1, &xtest1x, 20, false, false, false },
|
174 |
|
|
{ "Illegal instr test:\t\t\t",
|
175 |
|
|
xtest2, &xtest2x, 17, false, false, false },
|
176 |
|
|
{ "Divide instr test 1 (div):\t\t",
|
177 |
|
|
xtest3, &xtest3x, 19, false, false, false },
|
178 |
|
|
{ "Divide instr test 2 (divi):\t\t",
|
179 |
|
|
xtest4, &xtest4x, 19, false, false, false },
|
180 |
|
|
{ "Divide instr test 3 (divu):\t\t",
|
181 |
|
|
xtest5, &xtest5x, 19, false, false, false },
|
182 |
|
|
{ "Divide instr test 4 (divui):\t\t",
|
183 |
|
|
xtest6, &xtest6x, 19, false, false, false },
|
184 |
|
|
{ "Divide instr test 5 (rem):\t\t",
|
185 |
|
|
xtest7, &xtest7x, 19, false, false, false },
|
186 |
|
|
{ "Divide instr test 6 (remi):\t\t",
|
187 |
|
|
xtest8, &xtest8x, 19, false, false, false },
|
188 |
|
|
{ "Divide instr test 7 (remu):\t\t",
|
189 |
|
|
xtest9, &xtest9x, 19, false, false, false },
|
190 |
|
|
{ "Divide instr test 8 (remui):\t\t",
|
191 |
|
|
xtest10, &xtest10x, 19, false, false, false },
|
192 |
|
|
{ "Bus timeout test 1 (fetch):\t\t",
|
193 |
|
|
xtest11, &xtest11x, 16, false, false, false },
|
194 |
|
|
{ "Bus timeout test 2 (load):\t\t",
|
195 |
|
|
xtest12, &xtest12x, 16, false, false, false },
|
196 |
|
|
{ "Bus timeout test 3 (store):\t\t",
|
197 |
|
|
xtest13, &xtest13x, 16, false, false, false },
|
198 |
|
|
{ "Privileged instr test 1 (rfx):\t\t",
|
199 |
|
|
xtest14, &xtest14x, 18, true, false, false },
|
200 |
|
|
{ "Privileged instr test 2 (mvts):\t\t",
|
201 |
|
|
xtest15, &xtest15x, 18, true, false, false },
|
202 |
|
|
{ "Privileged instr test 3 (tb..):\t\t",
|
203 |
|
|
xtest16, &xtest16x, 18, true, false, false },
|
204 |
|
|
{ "Privileged address test 1 (fetch):\t",
|
205 |
|
|
xtest17, &xtest17x, 25, true, false, false },
|
206 |
|
|
{ "Privileged address test 2 (load):\t",
|
207 |
|
|
xtest18, &xtest18x, 25, true, false, false },
|
208 |
|
|
{ "Privileged address test 3 (store):\t",
|
209 |
|
|
xtest19, &xtest19x, 25, true, false, false },
|
210 |
|
|
{ "Illegal address test 1 (fetch):\t\t",
|
211 |
|
|
xtest20, &xtest20x, 24, false, false, false },
|
212 |
|
|
{ "Illegal address test 2 (fetch):\t\t",
|
213 |
|
|
xtest21, &xtest21x, 24, false, false, false },
|
214 |
|
|
{ "Illegal address test 3 (ldw):\t\t",
|
215 |
|
|
xtest22, &xtest22x, 24, false, false, false },
|
216 |
|
|
{ "Illegal address test 4 (ldw):\t\t",
|
217 |
|
|
xtest23, &xtest23x, 24, false, false, false },
|
218 |
|
|
{ "Illegal address test 5 (ldh):\t\t",
|
219 |
|
|
xtest24, &xtest24x, 24, false, false, false },
|
220 |
|
|
{ "Illegal address test 6 (stw):\t\t",
|
221 |
|
|
xtest25, &xtest25x, 24, false, false, false },
|
222 |
|
|
{ "Illegal address test 7 (stw):\t\t",
|
223 |
|
|
xtest26, &xtest26x, 24, false, false, false },
|
224 |
|
|
{ "Illegal address test 8 (sth):\t\t",
|
225 |
|
|
xtest27, &xtest27x, 24, false, false, false },
|
226 |
|
|
{ "TLB user miss test 1 (fetch):\t\t",
|
227 |
|
|
xtest28, &xtest28x, 21, false, true, true },
|
228 |
|
|
{ "TLB user miss test 2 (load):\t\t",
|
229 |
|
|
xtest29, &xtest29x, 21, false, true, true },
|
230 |
|
|
{ "TLB user miss test 3 (store):\t\t",
|
231 |
|
|
xtest30, &xtest30x, 21, false, true, true },
|
232 |
|
|
{ "TLB kernel miss test 1 (fetch):\t\t",
|
233 |
|
|
xtest31, &xtest31x, 21, false, true, false },
|
234 |
|
|
{ "TLB kernel miss test 2 (load):\t\t",
|
235 |
|
|
xtest32, &xtest32x, 21, false, true, false },
|
236 |
|
|
{ "TLB kernel miss test 3 (store):\t\t",
|
237 |
|
|
xtest33, &xtest33x, 21, false, true, false },
|
238 |
|
|
{ "TLB invalid test 1 (fetch):\t\t",
|
239 |
|
|
xtest34, &xtest34x, 23, false, true, false },
|
240 |
|
|
{ "TLB invalid test 2 (load):\t\t",
|
241 |
|
|
xtest35, &xtest35x, 23, false, true, false },
|
242 |
|
|
{ "TLB invalid test 3 (store):\t\t",
|
243 |
|
|
xtest36, &xtest36x, 23, false, true, false },
|
244 |
|
|
{ "TLB wrtprot test (store):\t\t",
|
245 |
|
|
xtest37, &xtest37x, 22, false, true, false },
|
246 |
|
|
};
|
247 |
|
|
|
248 |
|
|
|
249 |
|
|
int main(void) {
|
250 |
|
|
int i;
|
251 |
|
|
int result;
|
252 |
|
|
|
253 |
|
|
printf("\nStart of exception tests.\n\n");
|
254 |
|
|
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) {
|
255 |
|
|
printf("%s", tests[i].name);
|
256 |
|
|
result = execTest(tests[i].run,
|
257 |
|
|
tests[i].locus,
|
258 |
|
|
tests[i].exception,
|
259 |
|
|
tests[i].execInUserMode,
|
260 |
|
|
tests[i].clobberEntryHi,
|
261 |
|
|
tests[i].shouldTakeUserMiss);
|
262 |
|
|
if (result == 0) {
|
263 |
|
|
printf("ok");
|
264 |
|
|
} else {
|
265 |
|
|
printf("failed (%s)", errorMessage[result]);
|
266 |
|
|
}
|
267 |
|
|
printf("\n");
|
268 |
|
|
}
|
269 |
|
|
printf("\nEnd of exception tests.\n");
|
270 |
|
|
while (1) ;
|
271 |
|
|
return 0;
|
272 |
|
|
}
|