uboot/post/lib_powerpc/three.c
<<
>>
Prefs
   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 rD,rA,rB
  13 *
  14 * Arithmetic instructions:     add, addc, adde, subf, subfc, subfe,
  15 *                              mullw, mulhw, mulhwu, divw, divwu
  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
  27extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1,
  28    ulong op2);
  29extern ulong cpu_post_makecr (long v);
  30
  31static struct cpu_post_three_s
  32{
  33    ulong cmd;
  34    ulong op1;
  35    ulong op2;
  36    ulong res;
  37} cpu_post_three_table[] =
  38{
  39    {
  40        OP_ADD,
  41        100,
  42        200,
  43        300
  44    },
  45    {
  46        OP_ADD,
  47        100,
  48        -200,
  49        -100
  50    },
  51    {
  52        OP_ADDC,
  53        100,
  54        200,
  55        300
  56    },
  57    {
  58        OP_ADDC,
  59        100,
  60        -200,
  61        -100
  62    },
  63    {
  64        OP_ADDE,
  65        100,
  66        200,
  67        300
  68    },
  69    {
  70        OP_ADDE,
  71        100,
  72        -200,
  73        -100
  74    },
  75    {
  76        OP_SUBF,
  77        100,
  78        200,
  79        100
  80    },
  81    {
  82        OP_SUBF,
  83        300,
  84        200,
  85        -100
  86    },
  87    {
  88        OP_SUBFC,
  89        100,
  90        200,
  91        100
  92    },
  93    {
  94        OP_SUBFC,
  95        300,
  96        200,
  97        -100
  98    },
  99    {
 100        OP_SUBFE,
 101        100,
 102        200,
 103        200 + ~100
 104    },
 105    {
 106        OP_SUBFE,
 107        300,
 108        200,
 109        200 + ~300
 110    },
 111    {
 112        OP_MULLW,
 113        200,
 114        300,
 115        200 * 300
 116    },
 117    {
 118        OP_MULHW,
 119        0x10000000,
 120        0x10000000,
 121        0x1000000
 122    },
 123    {
 124        OP_MULHWU,
 125        0x80000000,
 126        0x80000000,
 127        0x40000000
 128    },
 129    {
 130        OP_DIVW,
 131        -20,
 132        5,
 133        -4
 134    },
 135    {
 136        OP_DIVWU,
 137        0x8000,
 138        0x200,
 139        0x40
 140    },
 141};
 142static unsigned int cpu_post_three_size = ARRAY_SIZE(cpu_post_three_table);
 143
 144int cpu_post_test_three (void)
 145{
 146    int ret = 0;
 147    unsigned int i, reg;
 148    int flag = disable_interrupts();
 149
 150    for (i = 0; i < cpu_post_three_size && ret == 0; i++)
 151    {
 152        struct cpu_post_three_s *test = cpu_post_three_table + i;
 153
 154        for (reg = 0; reg < 32 && ret == 0; reg++)
 155        {
 156            unsigned int reg0 = (reg + 0) % 32;
 157            unsigned int reg1 = (reg + 1) % 32;
 158            unsigned int reg2 = (reg + 2) % 32;
 159            unsigned int stk = reg < 16 ? 31 : 15;
 160            unsigned long code[] =
 161            {
 162                ASM_STW(stk, 1, -4),
 163                ASM_ADDI(stk, 1, -24),
 164                ASM_STW(3, stk, 12),
 165                ASM_STW(4, stk, 16),
 166                ASM_STW(reg0, stk, 8),
 167                ASM_STW(reg1, stk, 4),
 168                ASM_STW(reg2, stk, 0),
 169                ASM_LWZ(reg1, stk, 12),
 170                ASM_LWZ(reg0, stk, 16),
 171                ASM_12(test->cmd, reg2, reg1, reg0),
 172                ASM_STW(reg2, stk, 12),
 173                ASM_LWZ(reg2, stk, 0),
 174                ASM_LWZ(reg1, stk, 4),
 175                ASM_LWZ(reg0, stk, 8),
 176                ASM_LWZ(3, stk, 12),
 177                ASM_ADDI(1, stk, 24),
 178                ASM_LWZ(stk, 1, -4),
 179                ASM_BLR,
 180            };
 181            unsigned long codecr[] =
 182            {
 183                ASM_STW(stk, 1, -4),
 184                ASM_ADDI(stk, 1, -24),
 185                ASM_STW(3, stk, 12),
 186                ASM_STW(4, stk, 16),
 187                ASM_STW(reg0, stk, 8),
 188                ASM_STW(reg1, stk, 4),
 189                ASM_STW(reg2, stk, 0),
 190                ASM_LWZ(reg1, stk, 12),
 191                ASM_LWZ(reg0, stk, 16),
 192                ASM_12(test->cmd, reg2, reg1, reg0) | BIT_C,
 193                ASM_STW(reg2, stk, 12),
 194                ASM_LWZ(reg2, stk, 0),
 195                ASM_LWZ(reg1, stk, 4),
 196                ASM_LWZ(reg0, stk, 8),
 197                ASM_LWZ(3, stk, 12),
 198                ASM_ADDI(1, stk, 24),
 199                ASM_LWZ(stk, 1, -4),
 200                ASM_BLR,
 201            };
 202            ulong res;
 203            ulong cr;
 204
 205            if (ret == 0)
 206            {
 207                cr = 0;
 208                cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2);
 209
 210                ret = res == test->res && cr == 0 ? 0 : -1;
 211
 212                if (ret != 0)
 213                {
 214                    post_log ("Error at three test %d !\n", i);
 215                }
 216            }
 217
 218            if (ret == 0)
 219            {
 220                cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2);
 221
 222                ret = res == test->res &&
 223                      (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1;
 224
 225                if (ret != 0)
 226                {
 227                    post_log ("Error at three test %d !\n", i);
 228                }
 229            }
 230        }
 231    }
 232
 233    if (flag)
 234        enable_interrupts();
 235
 236    return ret;
 237}
 238
 239#endif
 240