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