]> git.ipfire.org Git - people/ms/u-boot.git/blame - post/lib_powerpc/three.c
Merge commit '7b2fac7654f7420c2787f74ec3b1540fa3b343e9'
[people/ms/u-boot.git] / post / lib_powerpc / three.c
CommitLineData
ad5bb451
WD
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 * 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
ad5bb451
WD
38#include <post.h>
39#include "cpu_asm.h"
40
6d0f6bcf 41#if CONFIG_POST & CONFIG_SYS_POST_CPU
ad5bb451
WD
42
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 {
53677ef1 56 OP_ADD,
ad5bb451
WD
57 100,
58 200,
59 300
60 },
61 {
53677ef1 62 OP_ADD,
ad5bb451
WD
63 100,
64 -200,
65 -100
66 },
67 {
53677ef1 68 OP_ADDC,
ad5bb451
WD
69 100,
70 200,
71 300
72 },
73 {
53677ef1 74 OP_ADDC,
ad5bb451
WD
75 100,
76 -200,
77 -100
78 },
79 {
53677ef1 80 OP_ADDE,
ad5bb451
WD
81 100,
82 200,
83 300
84 },
85 {
53677ef1 86 OP_ADDE,
ad5bb451
WD
87 100,
88 -200,
89 -100
90 },
91 {
53677ef1 92 OP_SUBF,
ad5bb451
WD
93 100,
94 200,
95 100
96 },
97 {
53677ef1 98 OP_SUBF,
ad5bb451
WD
99 300,
100 200,
101 -100
102 },
103 {
53677ef1 104 OP_SUBFC,
ad5bb451
WD
105 100,
106 200,
107 100
108 },
109 {
53677ef1 110 OP_SUBFC,
ad5bb451
WD
111 300,
112 200,
113 -100
114 },
115 {
53677ef1 116 OP_SUBFE,
ad5bb451
WD
117 100,
118 200,
119 200 + ~100
120 },
121 {
53677ef1 122 OP_SUBFE,
ad5bb451
WD
123 300,
124 200,
125 200 + ~300
126 },
127 {
53677ef1 128 OP_MULLW,
ad5bb451
WD
129 200,
130 300,
131 200 * 300
132 },
133 {
53677ef1 134 OP_MULHW,
ad5bb451
WD
135 0x10000000,
136 0x10000000,
137 0x1000000
138 },
139 {
53677ef1 140 OP_MULHWU,
ad5bb451
WD
141 0x80000000,
142 0x80000000,
143 0x40000000
144 },
145 {
53677ef1 146 OP_DIVW,
ad5bb451
WD
147 -20,
148 5,
149 -4
150 },
151 {
53677ef1 152 OP_DIVWU,
ad5bb451
WD
153 0x8000,
154 0x200,
155 0x40
156 },
157};
d2397817 158static unsigned int cpu_post_three_size = ARRAY_SIZE(cpu_post_three_table);
ad5bb451
WD
159
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;
53677ef1 176 unsigned long code[] =
ad5bb451
WD
177 {
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 };
53677ef1 197 unsigned long codecr[] =
ad5bb451
WD
198 {
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 {
53677ef1
WD
223 cr = 0;
224 cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
ad5bb451 225
53677ef1 226 ret = res == test->res && cr == 0 ? 0 : -1;
ad5bb451 227
53677ef1
WD
228 if (ret != 0)
229 {
ad5bb451 230 post_log ("Error at three test %d !\n", i);
53677ef1 231 }
ad5bb451
WD
232 }
233
234 if (ret == 0)
235 {
53677ef1 236 cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
ad5bb451 237
53677ef1 238 ret = res == test->res &&
ad5bb451
WD
239 (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
240
53677ef1
WD
241 if (ret != 0)
242 {
ad5bb451
WD
243 post_log ("Error at three test %d !\n", i);
244 }
245 }
246 }
247 }
248
249 if (flag)
53677ef1 250 enable_interrupts();
ad5bb451
WD
251
252 return ret;
253}
254
255#endif