Merge branch 'master' of git://git.denx.de/u-boot-arm
[platform/kernel/u-boot.git] / post / lib_powerpc / threex.c
1 /*
2  * (C) Copyright 2002
3  * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
4  *
5  * SPDX-License-Identifier:     GPL-2.0+
6  */
7
8 #include <common.h>
9
10 /*
11  * CPU test
12  * Ternary instructions         instr rA,rS,rB
13  *
14  * Logic instructions:          or, orc, xor, nand, nor, eqv
15  * Shift instructions:          slw, srw, sraw
16  *
17  * The test contains a pre-built table of instructions, operands and
18  * expected results. For each table entry, the test will cyclically use
19  * different sets of operand registers and result registers.
20  */
21
22 #include <post.h>
23 #include "cpu_asm.h"
24
25 #if CONFIG_POST & CONFIG_SYS_POST_CPU
26
27 extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
28     ulong op2);
29 extern ulong cpu_post_makecr (long v);
30
31 static struct cpu_post_threex_s
32 {
33     ulong cmd;
34     ulong op1;
35     ulong op2;
36     ulong res;
37 } cpu_post_threex_table[] =
38 {
39     {
40         OP_OR,
41         0x1234,
42         0x5678,
43         0x1234 | 0x5678
44     },
45     {
46         OP_ORC,
47         0x1234,
48         0x5678,
49         0x1234 | ~0x5678
50     },
51     {
52         OP_XOR,
53         0x1234,
54         0x5678,
55         0x1234 ^ 0x5678
56     },
57     {
58         OP_NAND,
59         0x1234,
60         0x5678,
61         ~(0x1234 & 0x5678)
62     },
63     {
64         OP_NOR,
65         0x1234,
66         0x5678,
67         ~(0x1234 | 0x5678)
68     },
69     {
70         OP_EQV,
71         0x1234,
72         0x5678,
73         ~(0x1234 ^ 0x5678)
74     },
75     {
76         OP_SLW,
77         0x80,
78         16,
79         0x800000
80     },
81     {
82         OP_SLW,
83         0x80,
84         32,
85         0
86     },
87     {
88         OP_SRW,
89         0x800000,
90         16,
91         0x80
92     },
93     {
94         OP_SRW,
95         0x800000,
96         32,
97         0
98     },
99     {
100         OP_SRAW,
101         0x80000000,
102         3,
103         0xf0000000
104     },
105     {
106         OP_SRAW,
107         0x8000,
108         3,
109         0x1000
110     },
111 };
112 static unsigned int cpu_post_threex_size = ARRAY_SIZE(cpu_post_threex_table);
113
114 int cpu_post_test_threex (void)
115 {
116     int ret = 0;
117     unsigned int i, reg;
118     int flag = disable_interrupts();
119
120     for (i = 0; i < cpu_post_threex_size && ret == 0; i++)
121     {
122         struct cpu_post_threex_s *test = cpu_post_threex_table + i;
123
124         for (reg = 0; reg < 32 && ret == 0; reg++)
125         {
126             unsigned int reg0 = (reg + 0) % 32;
127             unsigned int reg1 = (reg + 1) % 32;
128             unsigned int reg2 = (reg + 2) % 32;
129             unsigned int stk = reg < 16 ? 31 : 15;
130             unsigned long code[] =
131             {
132                 ASM_STW(stk, 1, -4),
133                 ASM_ADDI(stk, 1, -24),
134                 ASM_STW(3, stk, 12),
135                 ASM_STW(4, stk, 16),
136                 ASM_STW(reg0, stk, 8),
137                 ASM_STW(reg1, stk, 4),
138                 ASM_STW(reg2, stk, 0),
139                 ASM_LWZ(reg1, stk, 12),
140                 ASM_LWZ(reg0, stk, 16),
141                 ASM_12X(test->cmd, reg2, reg1, reg0),
142                 ASM_STW(reg2, stk, 12),
143                 ASM_LWZ(reg2, stk, 0),
144                 ASM_LWZ(reg1, stk, 4),
145                 ASM_LWZ(reg0, stk, 8),
146                 ASM_LWZ(3, stk, 12),
147                 ASM_ADDI(1, stk, 24),
148                 ASM_LWZ(stk, 1, -4),
149                 ASM_BLR,
150             };
151             unsigned long codecr[] =
152             {
153                 ASM_STW(stk, 1, -4),
154                 ASM_ADDI(stk, 1, -24),
155                 ASM_STW(3, stk, 12),
156                 ASM_STW(4, stk, 16),
157                 ASM_STW(reg0, stk, 8),
158                 ASM_STW(reg1, stk, 4),
159                 ASM_STW(reg2, stk, 0),
160                 ASM_LWZ(reg1, stk, 12),
161                 ASM_LWZ(reg0, stk, 16),
162                 ASM_12X(test->cmd, reg2, reg1, reg0) | BIT_C,
163                 ASM_STW(reg2, stk, 12),
164                 ASM_LWZ(reg2, stk, 0),
165                 ASM_LWZ(reg1, stk, 4),
166                 ASM_LWZ(reg0, stk, 8),
167                 ASM_LWZ(3, stk, 12),
168                 ASM_ADDI(1, stk, 24),
169                 ASM_LWZ(stk, 1, -4),
170                 ASM_BLR,
171             };
172             ulong res;
173             ulong cr;
174
175             if (ret == 0)
176             {
177                 cr = 0;
178                 cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
179
180                 ret = res == test->res && cr == 0 ? 0 : -1;
181
182                 if (ret != 0)
183                 {
184                     post_log ("Error at threex test %d !\n", i);
185                 }
186             }
187
188             if (ret == 0)
189             {
190                 cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
191
192                 ret = res == test->res &&
193                       (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
194
195                 if (ret != 0)
196                 {
197                     post_log ("Error at threex test %d !\n", i);
198                 }
199             }
200         }
201     }
202
203     if (flag)
204         enable_interrupts();
205
206     return ret;
207 }
208
209 #endif