blob: 4391386df1b0350cf05f589480a5f760daece99f [file] [log] [blame]
Wolfgang Denkb38e0df2007-03-06 18:08:43 +01001/*
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 * Ternary instructions instr rD,rA,rB
29 *
30 * Arithmetic instructions: add, addc, adde, subf, subfc, subfe,
31 * mullw, mulhw, mulhwu, divw, divwu
32 *
33 * The test contains a pre-built table of instructions, operands and
34 * expected results. For each table entry, the test will cyclically use
35 * different sets of operand registers and result registers.
36 */
37
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010038#include <post.h>
39#include "cpu_asm.h"
40
Jean-Christophe PLAGNIOL-VILLARD03836942008-10-16 15:01:15 +020041#if CONFIG_POST & CONFIG_SYS_POST_CPU
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010042
43extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
44 ulong op2);
45extern ulong cpu_post_makecr (long v);
46
47static struct cpu_post_three_s
48{
49 ulong cmd;
50 ulong op1;
51 ulong op2;
52 ulong res;
53} cpu_post_three_table[] =
54{
55 {
Wolfgang Denka1be4762008-05-20 16:00:29 +020056 OP_ADD,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010057 100,
58 200,
59 300
60 },
61 {
Wolfgang Denka1be4762008-05-20 16:00:29 +020062 OP_ADD,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010063 100,
64 -200,
65 -100
66 },
67 {
Wolfgang Denka1be4762008-05-20 16:00:29 +020068 OP_ADDC,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010069 100,
70 200,
71 300
72 },
73 {
Wolfgang Denka1be4762008-05-20 16:00:29 +020074 OP_ADDC,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010075 100,
76 -200,
77 -100
78 },
79 {
Wolfgang Denka1be4762008-05-20 16:00:29 +020080 OP_ADDE,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010081 100,
82 200,
83 300
84 },
85 {
Wolfgang Denka1be4762008-05-20 16:00:29 +020086 OP_ADDE,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010087 100,
88 -200,
89 -100
90 },
91 {
Wolfgang Denka1be4762008-05-20 16:00:29 +020092 OP_SUBF,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010093 100,
94 200,
95 100
96 },
97 {
Wolfgang Denka1be4762008-05-20 16:00:29 +020098 OP_SUBF,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +010099 300,
100 200,
101 -100
102 },
103 {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200104 OP_SUBFC,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100105 100,
106 200,
107 100
108 },
109 {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200110 OP_SUBFC,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100111 300,
112 200,
113 -100
114 },
115 {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200116 OP_SUBFE,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100117 100,
118 200,
119 200 + ~100
120 },
121 {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200122 OP_SUBFE,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100123 300,
124 200,
125 200 + ~300
126 },
127 {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200128 OP_MULLW,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100129 200,
130 300,
131 200 * 300
132 },
133 {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200134 OP_MULHW,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100135 0x10000000,
136 0x10000000,
137 0x1000000
138 },
139 {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200140 OP_MULHWU,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100141 0x80000000,
142 0x80000000,
143 0x40000000
144 },
145 {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200146 OP_DIVW,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100147 -20,
148 5,
149 -4
150 },
151 {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200152 OP_DIVWU,
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100153 0x8000,
154 0x200,
155 0x40
156 },
157};
Mike Frysinger83a687b2011-05-10 07:28:35 +0000158static unsigned int cpu_post_three_size = ARRAY_SIZE(cpu_post_three_table);
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100159
160int cpu_post_test_three (void)
161{
162 int ret = 0;
163 unsigned int i, reg;
164 int flag = disable_interrupts();
165
166 for (i = 0; i < cpu_post_three_size && ret == 0; i++)
167 {
168 struct cpu_post_three_s *test = cpu_post_three_table + i;
169
170 for (reg = 0; reg < 32 && ret == 0; reg++)
171 {
172 unsigned int reg0 = (reg + 0) % 32;
173 unsigned int reg1 = (reg + 1) % 32;
174 unsigned int reg2 = (reg + 2) % 32;
175 unsigned int stk = reg < 16 ? 31 : 15;
Wolfgang Denka1be4762008-05-20 16:00:29 +0200176 unsigned long code[] =
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100177 {
178 ASM_STW(stk, 1, -4),
179 ASM_ADDI(stk, 1, -24),
180 ASM_STW(3, stk, 12),
181 ASM_STW(4, stk, 16),
182 ASM_STW(reg0, stk, 8),
183 ASM_STW(reg1, stk, 4),
184 ASM_STW(reg2, stk, 0),
185 ASM_LWZ(reg1, stk, 12),
186 ASM_LWZ(reg0, stk, 16),
187 ASM_12(test->cmd, reg2, reg1, reg0),
188 ASM_STW(reg2, stk, 12),
189 ASM_LWZ(reg2, stk, 0),
190 ASM_LWZ(reg1, stk, 4),
191 ASM_LWZ(reg0, stk, 8),
192 ASM_LWZ(3, stk, 12),
193 ASM_ADDI(1, stk, 24),
194 ASM_LWZ(stk, 1, -4),
195 ASM_BLR,
196 };
Wolfgang Denka1be4762008-05-20 16:00:29 +0200197 unsigned long codecr[] =
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100198 {
199 ASM_STW(stk, 1, -4),
200 ASM_ADDI(stk, 1, -24),
201 ASM_STW(3, stk, 12),
202 ASM_STW(4, stk, 16),
203 ASM_STW(reg0, stk, 8),
204 ASM_STW(reg1, stk, 4),
205 ASM_STW(reg2, stk, 0),
206 ASM_LWZ(reg1, stk, 12),
207 ASM_LWZ(reg0, stk, 16),
208 ASM_12(test->cmd, reg2, reg1, reg0) | BIT_C,
209 ASM_STW(reg2, stk, 12),
210 ASM_LWZ(reg2, stk, 0),
211 ASM_LWZ(reg1, stk, 4),
212 ASM_LWZ(reg0, stk, 8),
213 ASM_LWZ(3, stk, 12),
214 ASM_ADDI(1, stk, 24),
215 ASM_LWZ(stk, 1, -4),
216 ASM_BLR,
217 };
218 ulong res;
219 ulong cr;
220
221 if (ret == 0)
222 {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200223 cr = 0;
224 cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100225
Wolfgang Denka1be4762008-05-20 16:00:29 +0200226 ret = res == test->res && cr == 0 ? 0 : -1;
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100227
Wolfgang Denka1be4762008-05-20 16:00:29 +0200228 if (ret != 0)
229 {
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100230 post_log ("Error at three test %d !\n", i);
Wolfgang Denka1be4762008-05-20 16:00:29 +0200231 }
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100232 }
233
234 if (ret == 0)
235 {
Wolfgang Denka1be4762008-05-20 16:00:29 +0200236 cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100237
Wolfgang Denka1be4762008-05-20 16:00:29 +0200238 ret = res == test->res &&
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100239 (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
240
Wolfgang Denka1be4762008-05-20 16:00:29 +0200241 if (ret != 0)
242 {
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100243 post_log ("Error at three test %d !\n", i);
244 }
245 }
246 }
247 }
248
249 if (flag)
Wolfgang Denka1be4762008-05-20 16:00:29 +0200250 enable_interrupts();
Wolfgang Denkb38e0df2007-03-06 18:08:43 +0100251
252 return ret;
253}
254
255#endif