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 * Binary instructions instr rA,rS 12 * 13 * Logic instructions: cntlzw 14 * Arithmetic instructions: extsb, extsh 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_21 (ulong *code, ulong *cr, ulong *res, ulong op1); 27 extern ulong cpu_post_makecr (long v); 28 29 static struct cpu_post_twox_s 30 { 31 ulong cmd; 32 ulong op; 33 ulong res; 34 } cpu_post_twox_table[] = 35 { 36 { 37 OP_EXTSB, 38 3, 39 3 40 }, 41 { 42 OP_EXTSB, 43 0xff, 44 -1 45 }, 46 { 47 OP_EXTSH, 48 3, 49 3 50 }, 51 { 52 OP_EXTSH, 53 0xff, 54 0xff 55 }, 56 { 57 OP_EXTSH, 58 0xffff, 59 -1 60 }, 61 { 62 OP_CNTLZW, 63 0x000fffff, 64 12 65 }, 66 }; 67 static unsigned int cpu_post_twox_size = ARRAY_SIZE(cpu_post_twox_table); 68 69 int cpu_post_test_twox (void) 70 { 71 int ret = 0; 72 unsigned int i, reg; 73 int flag = disable_interrupts(); 74 75 for (i = 0; i < cpu_post_twox_size && ret == 0; i++) 76 { 77 struct cpu_post_twox_s *test = cpu_post_twox_table + i; 78 79 for (reg = 0; reg < 32 && ret == 0; reg++) 80 { 81 unsigned int reg0 = (reg + 0) % 32; 82 unsigned int reg1 = (reg + 1) % 32; 83 unsigned int stk = reg < 16 ? 31 : 15; 84 unsigned long code[] = 85 { 86 ASM_STW(stk, 1, -4), 87 ASM_ADDI(stk, 1, -16), 88 ASM_STW(3, stk, 8), 89 ASM_STW(reg0, stk, 4), 90 ASM_STW(reg1, stk, 0), 91 ASM_LWZ(reg0, stk, 8), 92 ASM_11X(test->cmd, reg1, reg0), 93 ASM_STW(reg1, stk, 8), 94 ASM_LWZ(reg1, stk, 0), 95 ASM_LWZ(reg0, stk, 4), 96 ASM_LWZ(3, stk, 8), 97 ASM_ADDI(1, stk, 16), 98 ASM_LWZ(stk, 1, -4), 99 ASM_BLR, 100 }; 101 unsigned long codecr[] = 102 { 103 ASM_STW(stk, 1, -4), 104 ASM_ADDI(stk, 1, -16), 105 ASM_STW(3, stk, 8), 106 ASM_STW(reg0, stk, 4), 107 ASM_STW(reg1, stk, 0), 108 ASM_LWZ(reg0, stk, 8), 109 ASM_11X(test->cmd, reg1, reg0) | BIT_C, 110 ASM_STW(reg1, stk, 8), 111 ASM_LWZ(reg1, stk, 0), 112 ASM_LWZ(reg0, stk, 4), 113 ASM_LWZ(3, stk, 8), 114 ASM_ADDI(1, stk, 16), 115 ASM_LWZ(stk, 1, -4), 116 ASM_BLR, 117 }; 118 ulong res; 119 ulong cr; 120 121 if (ret == 0) 122 { 123 cr = 0; 124 cpu_post_exec_21 (code, & cr, & res, test->op); 125 126 ret = res == test->res && cr == 0 ? 0 : -1; 127 128 if (ret != 0) 129 { 130 post_log ("Error at twox test %d !\n", i); 131 } 132 } 133 134 if (ret == 0) 135 { 136 cpu_post_exec_21 (codecr, & cr, & res, test->op); 137 138 ret = res == test->res && 139 (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; 140 141 if (ret != 0) 142 { 143 post_log ("Error at twox test %d !\n", i); 144 } 145 } 146 } 147 } 148 149 if (flag) 150 enable_interrupts(); 151 152 return ret; 153 } 154 155 #endif 156