Merge branch 'cleanups' into next
[platform/kernel/u-boot.git] / post / lib_ppc / two.c
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  * Binary instructions          instr rD,rA
29  *
30  * Logic instructions:          neg
31  * Arithmetic instructions:     addme, addze, subfme, subfze
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
38 #include <post.h>
39 #include "cpu_asm.h"
40
41 #if CONFIG_POST & CONFIG_SYS_POST_CPU
42
43 extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1);
44 extern ulong cpu_post_makecr (long v);
45
46 static struct cpu_post_two_s
47 {
48     ulong cmd;
49     ulong op;
50     ulong res;
51 } cpu_post_two_table[] =
52 {
53     {
54         OP_NEG,
55         3,
56         -3
57     },
58     {
59         OP_NEG,
60         5,
61         -5
62     },
63     {
64         OP_ADDME,
65         6,
66         5
67     },
68     {
69         OP_ADDZE,
70         5,
71         5
72     },
73     {
74         OP_SUBFME,
75         6,
76         ~6 - 1
77     },
78     {
79         OP_SUBFZE,
80         5,
81         ~5
82     },
83 };
84 static unsigned int cpu_post_two_size =
85     sizeof (cpu_post_two_table) / sizeof (struct cpu_post_two_s);
86
87 int cpu_post_test_two (void)
88 {
89     int ret = 0;
90     unsigned int i, reg;
91     int flag = disable_interrupts();
92
93     for (i = 0; i < cpu_post_two_size && ret == 0; i++)
94     {
95         struct cpu_post_two_s *test = cpu_post_two_table + i;
96
97         for (reg = 0; reg < 32 && ret == 0; reg++)
98         {
99             unsigned int reg0 = (reg + 0) % 32;
100             unsigned int reg1 = (reg + 1) % 32;
101             unsigned int stk = reg < 16 ? 31 : 15;
102             unsigned long code[] =
103             {
104                 ASM_STW(stk, 1, -4),
105                 ASM_ADDI(stk, 1, -16),
106                 ASM_STW(3, stk, 8),
107                 ASM_STW(reg0, stk, 4),
108                 ASM_STW(reg1, stk, 0),
109                 ASM_LWZ(reg0, stk, 8),
110                 ASM_11(test->cmd, reg1, reg0),
111                 ASM_STW(reg1, stk, 8),
112                 ASM_LWZ(reg1, stk, 0),
113                 ASM_LWZ(reg0, stk, 4),
114                 ASM_LWZ(3, stk, 8),
115                 ASM_ADDI(1, stk, 16),
116                 ASM_LWZ(stk, 1, -4),
117                 ASM_BLR,
118             };
119             unsigned long codecr[] =
120             {
121                 ASM_STW(stk, 1, -4),
122                 ASM_ADDI(stk, 1, -16),
123                 ASM_STW(3, stk, 8),
124                 ASM_STW(reg0, stk, 4),
125                 ASM_STW(reg1, stk, 0),
126                 ASM_LWZ(reg0, stk, 8),
127                 ASM_11(test->cmd, reg1, reg0) | BIT_C,
128                 ASM_STW(reg1, stk, 8),
129                 ASM_LWZ(reg1, stk, 0),
130                 ASM_LWZ(reg0, stk, 4),
131                 ASM_LWZ(3, stk, 8),
132                 ASM_ADDI(1, stk, 16),
133                 ASM_LWZ(stk, 1, -4),
134                 ASM_BLR,
135             };
136             ulong res;
137             ulong cr;
138
139             if (ret == 0)
140             {
141                 cr = 0;
142                 cpu_post_exec_21 (code, & cr, & res, test->op);
143
144                 ret = res == test->res && cr == 0 ? 0 : -1;
145
146                 if (ret != 0)
147                 {
148                     post_log ("Error at two test %d !\n", i);
149                 }
150             }
151
152             if (ret == 0)
153             {
154                 cpu_post_exec_21 (codecr, & cr, & res, test->op);
155
156                 ret = res == test->res &&
157                       (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
158
159                 if (ret != 0)
160                 {
161                     post_log ("Error at two test %d !\n", i);
162                 }
163             }
164         }
165     }
166
167     if (flag)
168         enable_interrupts();
169
170     return ret;
171 }
172
173 #endif