1 /*
2  * (C) Copyright 2002
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * See file CREDITS for list of people who contributed to this
6  * project.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of
11  * the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
21  * MA 02111-1307 USA
22  */
23 
24 #include <common.h>
25 
26 /*
27  * CPU test
28  * Load instructions:		lbz(x)(u), lhz(x)(u), lha(x)(u), lwz(x)(u)
29  *
30  * All operations are performed on a 16-byte array. The array
31  * is 4-byte aligned. The base register points to offset 8.
32  * The immediate offset (index register) ranges in [-8 ... +7].
33  * The test cases are composed so that they do not
34  * cause alignment exceptions.
35  * The test contains a pre-built table describing all test cases.
36  * The table entry contains:
37  * the instruction opcode, the array contents, the value of the index
38  * register and the expected value of the destination register.
39  * After executing the instruction, the test verifies the
40  * value of the destination register and the value of the base
41  * register (it must change for "load with update" instructions).
42  */
43 
44 #include <post.h>
45 #include "cpu_asm.h"
46 
47 #if CONFIG_POST & CONFIG_SYS_POST_CPU
48 
49 extern void cpu_post_exec_22w (ulong *code, ulong *op1, ulong op2, ulong *op3);
50 extern void cpu_post_exec_21w (ulong *code, ulong *op1, ulong *op2);
51 
52 static struct cpu_post_load_s
53 {
54     ulong cmd;
55     uint width;
56     int update;
57     int index;
58     ulong offset;
59 } cpu_post_load_table[] =
60 {
61     {
62 	OP_LWZ,
63 	4,
64 	0,
65 	0,
66 	4
67     },
68     {
69 	OP_LHA,
70 	3,
71 	0,
72 	0,
73 	2
74     },
75     {
76 	OP_LHZ,
77 	2,
78 	0,
79 	0,
80 	2
81     },
82     {
83 	OP_LBZ,
84 	1,
85 	0,
86 	0,
87 	1
88     },
89     {
90 	OP_LWZU,
91 	4,
92 	1,
93 	0,
94 	4
95     },
96     {
97 	OP_LHAU,
98 	3,
99 	1,
100 	0,
101 	2
102     },
103     {
104 	OP_LHZU,
105 	2,
106 	1,
107 	0,
108 	2
109     },
110     {
111 	OP_LBZU,
112 	1,
113 	1,
114 	0,
115 	1
116     },
117     {
118 	OP_LWZX,
119 	4,
120 	0,
121 	1,
122 	4
123     },
124     {
125 	OP_LHAX,
126 	3,
127 	0,
128 	1,
129 	2
130     },
131     {
132 	OP_LHZX,
133 	2,
134 	0,
135 	1,
136 	2
137     },
138     {
139 	OP_LBZX,
140 	1,
141 	0,
142 	1,
143 	1
144     },
145     {
146 	OP_LWZUX,
147 	4,
148 	1,
149 	1,
150 	4
151     },
152     {
153 	OP_LHAUX,
154 	3,
155 	1,
156 	1,
157 	2
158     },
159     {
160 	OP_LHZUX,
161 	2,
162 	1,
163 	1,
164 	2
165     },
166     {
167 	OP_LBZUX,
168 	1,
169 	1,
170 	1,
171 	1
172     },
173 };
174 static unsigned int cpu_post_load_size =
175     sizeof (cpu_post_load_table) / sizeof (struct cpu_post_load_s);
176 
cpu_post_test_load(void)177 int cpu_post_test_load (void)
178 {
179     int ret = 0;
180     unsigned int i;
181     int flag = disable_interrupts();
182 
183     for (i = 0; i < cpu_post_load_size && ret == 0; i++)
184     {
185 	struct cpu_post_load_s *test = cpu_post_load_table + i;
186 	uchar data[16] =
187 	{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
188 	ulong base0 = (ulong) (data + 8);
189 	ulong base = base0;
190 	ulong value;
191 
192 	if (test->index)
193 	{
194 	    ulong code[] =
195 	    {
196 		ASM_12(test->cmd, 5, 3, 4),
197 		ASM_BLR,
198 	    };
199 
200 	    cpu_post_exec_22w (code, &base, test->offset, &value);
201 	}
202 	else
203 	{
204 	    ulong code[] =
205 	    {
206 		ASM_11I(test->cmd, 4, 3, test->offset),
207 		ASM_BLR,
208 	    };
209 
210 	    cpu_post_exec_21w (code, &base, &value);
211 	}
212 
213 	if (ret == 0)
214 	{
215 	   if (test->update)
216 	       ret = base == base0 + test->offset ? 0 : -1;
217 	   else
218 	       ret = base == base0 ? 0 : -1;
219 	}
220 
221 	if (ret == 0)
222 	{
223 	    switch (test->width)
224 	    {
225 	    case 1:
226 		ret = *(uchar *)(base0 + test->offset) == value ?
227 		      0 : -1;
228 		break;
229 	    case 2:
230 		ret = *(ushort *)(base0 + test->offset) == value ?
231 		      0 : -1;
232 		break;
233 	    case 3:
234 		ret = *(short *)(base0 + test->offset) == value ?
235 		      0 : -1;
236 		break;
237 	    case 4:
238 		ret = *(ulong *)(base0 + test->offset) == value ?
239 		      0 : -1;
240 		break;
241 	    }
242 	}
243 
244 	if (ret != 0)
245 	{
246 	    post_log ("Error at load test %d !\n", i);
247 	}
248     }
249 
250     if (flag)
251 	enable_interrupts();
252 
253     return ret;
254 }
255 
256 #endif
257