uboot/post/lib_powerpc/threex.c
<<
>>
Prefs
   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 rA,rS,rB
  29 *
  30 * Logic instructions:          or, orc, xor, nand, nor, eqv
  31 * Shift instructions:          slw, srw, sraw
  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
  43extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
  44    ulong op2);
  45extern ulong cpu_post_makecr (long v);
  46
  47static struct cpu_post_threex_s
  48{
  49    ulong cmd;
  50    ulong op1;
  51    ulong op2;
  52    ulong res;
  53} cpu_post_threex_table[] =
  54{
  55    {
  56        OP_OR,
  57        0x1234,
  58        0x5678,
  59        0x1234 | 0x5678
  60    },
  61    {
  62        OP_ORC,
  63        0x1234,
  64        0x5678,
  65        0x1234 | ~0x5678
  66    },
  67    {
  68        OP_XOR,
  69        0x1234,
  70        0x5678,
  71        0x1234 ^ 0x5678
  72    },
  73    {
  74        OP_NAND,
  75        0x1234,
  76        0x5678,
  77        ~(0x1234 & 0x5678)
  78    },
  79    {
  80        OP_NOR,
  81        0x1234,
  82        0x5678,
  83        ~(0x1234 | 0x5678)
  84    },
  85    {
  86        OP_EQV,
  87        0x1234,
  88        0x5678,
  89        ~(0x1234 ^ 0x5678)
  90    },
  91    {
  92        OP_SLW,
  93        0x80,
  94        16,
  95        0x800000
  96    },
  97    {
  98        OP_SLW,
  99        0x80,
 100        32,
 101        0
 102    },
 103    {
 104        OP_SRW,
 105        0x800000,
 106        16,
 107        0x80
 108    },
 109    {
 110        OP_SRW,
 111        0x800000,
 112        32,
 113        0
 114    },
 115    {
 116        OP_SRAW,
 117        0x80000000,
 118        3,
 119        0xf0000000
 120    },
 121    {
 122        OP_SRAW,
 123        0x8000,
 124        3,
 125        0x1000
 126    },
 127};
 128static unsigned int cpu_post_threex_size =
 129    sizeof (cpu_post_threex_table) / sizeof (struct cpu_post_threex_s);
 130
 131int cpu_post_test_threex (void)
 132{
 133    int ret = 0;
 134    unsigned int i, reg;
 135    int flag = disable_interrupts();
 136
 137    for (i = 0; i < cpu_post_threex_size && ret == 0; i++)
 138    {
 139        struct cpu_post_threex_s *test = cpu_post_threex_table + i;
 140
 141        for (reg = 0; reg < 32 && ret == 0; reg++)
 142        {
 143            unsigned int reg0 = (reg + 0) % 32;
 144            unsigned int reg1 = (reg + 1) % 32;
 145            unsigned int reg2 = (reg + 2) % 32;
 146            unsigned int stk = reg < 16 ? 31 : 15;
 147            unsigned long code[] =
 148            {
 149                ASM_STW(stk, 1, -4),
 150                ASM_ADDI(stk, 1, -24),
 151                ASM_STW(3, stk, 12),
 152                ASM_STW(4, stk, 16),
 153                ASM_STW(reg0, stk, 8),
 154                ASM_STW(reg1, stk, 4),
 155                ASM_STW(reg2, stk, 0),
 156                ASM_LWZ(reg1, stk, 12),
 157                ASM_LWZ(reg0, stk, 16),
 158                ASM_12X(test->cmd, reg2, reg1, reg0),
 159                ASM_STW(reg2, stk, 12),
 160                ASM_LWZ(reg2, stk, 0),
 161                ASM_LWZ(reg1, stk, 4),
 162                ASM_LWZ(reg0, stk, 8),
 163                ASM_LWZ(3, stk, 12),
 164                ASM_ADDI(1, stk, 24),
 165                ASM_LWZ(stk, 1, -4),
 166                ASM_BLR,
 167            };
 168            unsigned long codecr[] =
 169            {
 170                ASM_STW(stk, 1, -4),
 171                ASM_ADDI(stk, 1, -24),
 172                ASM_STW(3, stk, 12),
 173                ASM_STW(4, stk, 16),
 174                ASM_STW(reg0, stk, 8),
 175                ASM_STW(reg1, stk, 4),
 176                ASM_STW(reg2, stk, 0),
 177                ASM_LWZ(reg1, stk, 12),
 178                ASM_LWZ(reg0, stk, 16),
 179                ASM_12X(test->cmd, reg2, reg1, reg0) | BIT_C,
 180                ASM_STW(reg2, stk, 12),
 181                ASM_LWZ(reg2, stk, 0),
 182                ASM_LWZ(reg1, stk, 4),
 183                ASM_LWZ(reg0, stk, 8),
 184                ASM_LWZ(3, stk, 12),
 185                ASM_ADDI(1, stk, 24),
 186                ASM_LWZ(stk, 1, -4),
 187                ASM_BLR,
 188            };
 189            ulong res;
 190            ulong cr;
 191
 192            if (ret == 0)
 193            {
 194                cr = 0;
 195                cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
 196
 197                ret = res == test->res && cr == 0 ? 0 : -1;
 198
 199                if (ret != 0)
 200                {
 201                    post_log ("Error at threex test %d !\n", i);
 202                }
 203            }
 204
 205            if (ret == 0)
 206            {
 207                cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
 208
 209                ret = res == test->res &&
 210                      (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
 211
 212                if (ret != 0)
 213                {
 214                    post_log ("Error at threex test %d !\n", i);
 215                }
 216            }
 217        }
 218    }
 219
 220    if (flag)
 221        enable_interrupts();
 222
 223    return ret;
 224}
 225
 226#endif
 227