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