]> git.ipfire.org Git - people/ms/u-boot.git/blame - post/lib_powerpc/three.c
Move arch/ppc to arch/powerpc
[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};
158static unsigned int cpu_post_three_size =
159 sizeof (cpu_post_three_table) / sizeof (struct cpu_post_three_s);
160
161int cpu_post_test_three (void)
162{
163 int ret = 0;
164 unsigned int i, reg;
165 int flag = disable_interrupts();
166
167 for (i = 0; i < cpu_post_three_size && ret == 0; i++)
168 {
169 struct cpu_post_three_s *test = cpu_post_three_table + i;
170
171 for (reg = 0; reg < 32 && ret == 0; reg++)
172 {
173 unsigned int reg0 = (reg + 0) % 32;
174 unsigned int reg1 = (reg + 1) % 32;
175 unsigned int reg2 = (reg + 2) % 32;
176 unsigned int stk = reg < 16 ? 31 : 15;
53677ef1 177 unsigned long code[] =
ad5bb451
WD
178 {
179 ASM_STW(stk, 1, -4),
180 ASM_ADDI(stk, 1, -24),
181 ASM_STW(3, stk, 12),
182 ASM_STW(4, stk, 16),
183 ASM_STW(reg0, stk, 8),
184 ASM_STW(reg1, stk, 4),
185 ASM_STW(reg2, stk, 0),
186 ASM_LWZ(reg1, stk, 12),
187 ASM_LWZ(reg0, stk, 16),
188 ASM_12(test->cmd, reg2, reg1, reg0),
189 ASM_STW(reg2, stk, 12),
190 ASM_LWZ(reg2, stk, 0),
191 ASM_LWZ(reg1, stk, 4),
192 ASM_LWZ(reg0, stk, 8),
193 ASM_LWZ(3, stk, 12),
194 ASM_ADDI(1, stk, 24),
195 ASM_LWZ(stk, 1, -4),
196 ASM_BLR,
197 };
53677ef1 198 unsigned long codecr[] =
ad5bb451
WD
199 {
200 ASM_STW(stk, 1, -4),
201 ASM_ADDI(stk, 1, -24),
202 ASM_STW(3, stk, 12),
203 ASM_STW(4, stk, 16),
204 ASM_STW(reg0, stk, 8),
205 ASM_STW(reg1, stk, 4),
206 ASM_STW(reg2, stk, 0),
207 ASM_LWZ(reg1, stk, 12),
208 ASM_LWZ(reg0, stk, 16),
209 ASM_12(test->cmd, reg2, reg1, reg0) | BIT_C,
210 ASM_STW(reg2, stk, 12),
211 ASM_LWZ(reg2, stk, 0),
212 ASM_LWZ(reg1, stk, 4),
213 ASM_LWZ(reg0, stk, 8),
214 ASM_LWZ(3, stk, 12),
215 ASM_ADDI(1, stk, 24),
216 ASM_LWZ(stk, 1, -4),
217 ASM_BLR,
218 };
219 ulong res;
220 ulong cr;
221
222 if (ret == 0)
223 {
53677ef1
WD
224 cr = 0;
225 cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
ad5bb451 226
53677ef1 227 ret = res == test->res && cr == 0 ? 0 : -1;
ad5bb451 228
53677ef1
WD
229 if (ret != 0)
230 {
ad5bb451 231 post_log ("Error at three test %d !\n", i);
53677ef1 232 }
ad5bb451
WD
233 }
234
235 if (ret == 0)
236 {
53677ef1 237 cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
ad5bb451 238
53677ef1 239 ret = res == test->res &&
ad5bb451
WD
240 (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
241
53677ef1
WD
242 if (ret != 0)
243 {
ad5bb451
WD
244 post_log ("Error at three test %d !\n", i);
245 }
246 }
247 }
248 }
249
250 if (flag)
53677ef1 251 enable_interrupts();
ad5bb451
WD
252
253 return ret;
254}
255
256#endif