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 209