uboot/post/lib_powerpc/three.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 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
  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_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};
 158static unsigned int cpu_post_three_size = ARRAY_SIZE(cpu_post_three_table);
 159
 160int 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