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 210