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