From ad5bb451ade552c44bef9119d907929ebc2c126f Mon Sep 17 00:00:00 2001 From: Wolfgang Denk Date: Tue, 6 Mar 2007 18:08:43 +0100 Subject: Restructure POST directory to support of other CPUs, boards, etc. --- post/lib_ppc/Makefile | 32 +++++ post/lib_ppc/andi.c | 123 +++++++++++++++++ post/lib_ppc/asm.S | 346 +++++++++++++++++++++++++++++++++++++++++++++++ post/lib_ppc/b.c | 197 +++++++++++++++++++++++++++ post/lib_ppc/cmp.c | 133 ++++++++++++++++++ post/lib_ppc/cmpi.c | 133 ++++++++++++++++++ post/lib_ppc/complex.c | 126 +++++++++++++++++ post/lib_ppc/cpu.c | 139 +++++++++++++++++++ post/lib_ppc/cpu_asm.h | 224 +++++++++++++++++++++++++++++++ post/lib_ppc/cr.c | 356 +++++++++++++++++++++++++++++++++++++++++++++++++ post/lib_ppc/load.c | 255 +++++++++++++++++++++++++++++++++++ post/lib_ppc/multi.c | 81 +++++++++++ post/lib_ppc/rlwimi.c | 162 ++++++++++++++++++++++ post/lib_ppc/rlwinm.c | 155 +++++++++++++++++++++ post/lib_ppc/rlwnm.c | 165 +++++++++++++++++++++++ post/lib_ppc/srawi.c | 156 ++++++++++++++++++++++ post/lib_ppc/store.c | 235 ++++++++++++++++++++++++++++++++ post/lib_ppc/string.c | 106 +++++++++++++++ post/lib_ppc/three.c | 259 +++++++++++++++++++++++++++++++++++ post/lib_ppc/threei.c | 137 +++++++++++++++++++ post/lib_ppc/threex.c | 229 +++++++++++++++++++++++++++++++ post/lib_ppc/two.c | 176 ++++++++++++++++++++++++ post/lib_ppc/twox.c | 176 ++++++++++++++++++++++++ 23 files changed, 4101 insertions(+) create mode 100644 post/lib_ppc/Makefile create mode 100644 post/lib_ppc/andi.c create mode 100644 post/lib_ppc/asm.S create mode 100644 post/lib_ppc/b.c create mode 100644 post/lib_ppc/cmp.c create mode 100644 post/lib_ppc/cmpi.c create mode 100644 post/lib_ppc/complex.c create mode 100644 post/lib_ppc/cpu.c create mode 100644 post/lib_ppc/cpu_asm.h create mode 100644 post/lib_ppc/cr.c create mode 100644 post/lib_ppc/load.c create mode 100644 post/lib_ppc/multi.c create mode 100644 post/lib_ppc/rlwimi.c create mode 100644 post/lib_ppc/rlwinm.c create mode 100644 post/lib_ppc/rlwnm.c create mode 100644 post/lib_ppc/srawi.c create mode 100644 post/lib_ppc/store.c create mode 100644 post/lib_ppc/string.c create mode 100644 post/lib_ppc/three.c create mode 100644 post/lib_ppc/threei.c create mode 100644 post/lib_ppc/threex.c create mode 100644 post/lib_ppc/two.c create mode 100644 post/lib_ppc/twox.c (limited to 'post/lib_ppc') diff --git a/post/lib_ppc/Makefile b/post/lib_ppc/Makefile new file mode 100644 index 00000000000..14354a03236 --- /dev/null +++ b/post/lib_ppc/Makefile @@ -0,0 +1,32 @@ +# +# (C) Copyright 2002-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + + +LIB = libpostppc.a + +AOBJS = asm.o +COBJS = cpu.o cmp.o cmpi.o two.o twox.o three.o threex.o +COBJS += threei.o andi.o srawi.o rlwnm.o rlwinm.o rlwimi.o +COBJS += store.o load.o cr.o b.o multi.o string.o complex.o + +include $(TOPDIR)/post/rules.mk diff --git a/post/lib_ppc/andi.c b/post/lib_ppc/andi.c new file mode 100644 index 00000000000..7ddf2ab2f3b --- /dev/null +++ b/post/lib_ppc/andi.c @@ -0,0 +1,123 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Logic instructions: andi., andis. + * + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_andi_s +{ + ulong cmd; + ulong op1; + ushort op2; + ulong res; +} cpu_post_andi_table[] = +{ + { + OP_ANDI_, + 0x80008000, + 0xffff, + 0x00008000 + }, + { + OP_ANDIS_, + 0x80008000, + 0xffff, + 0x80000000 + }, +}; +static unsigned int cpu_post_andi_size = + sizeof (cpu_post_andi_table) / sizeof (struct cpu_post_andi_s); + +int cpu_post_test_andi (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_andi_size && ret == 0; i++) + { + struct cpu_post_andi_s *test = cpu_post_andi_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long codecr[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_11IX(test->cmd, reg1, reg0, test->op2), + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + cpu_post_exec_21 (codecr, & cr, & res, test->op1); + + ret = res == test->res && + (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at andi test %d !\n", i); + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/asm.S b/post/lib_ppc/asm.S new file mode 100644 index 00000000000..a0815a43a77 --- /dev/null +++ b/post/lib_ppc/asm.S @@ -0,0 +1,346 @@ +/* + * Copyright (C) 2002 Wolfgang Denk + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +#ifdef CONFIG_POST + +#include +#include +#include +#include + +#if CONFIG_POST & CFG_POST_CPU + +/* void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2); */ + .global cpu_post_exec_02 +cpu_post_exec_02: + mflr r0 + stwu r0, -4(r1) + + subi r1, r1, 104 + stmw r6, 0(r1) + + mtlr r3 + mr r3, r4 + mr r4, r5 + blrl + + lmw r6, 0(r1) + addi r1, r1, 104 + + lwz r0, 0(r1) + addi r1, r1, 4 + mtlr r0 + blr + +/* void cpu_post_exec_04 (ulong *code, ulong op1, ulong op2, ulong op3, ulong op4); */ + .global cpu_post_exec_04 +cpu_post_exec_04: + mflr r0 + stwu r0, -4(r1) + + subi r1, r1, 96 + stmw r8, 0(r1) + + mtlr r3 + mr r3, r4 + mr r4, r5 + mr r5, r6 + mtxer r7 + blrl + + lmw r8, 0(r1) + addi r1, r1, 96 + + lwz r0, 0(r1) + addi r1, r1, 4 + mtlr r0 + blr + +/* void cpu_post_exec_12 (ulong *code, ulong *res, ulong op1, ulong op2); */ + .global cpu_post_exec_12 +cpu_post_exec_12: + mflr r0 + stwu r0, -4(r1) + stwu r4, -4(r1) + + mtlr r3 + mr r3, r5 + mr r4, r6 + blrl + + lwz r4, 0(r1) + stw r3, 0(r4) + + lwz r0, 4(r1) + addi r1, r1, 8 + mtlr r0 + blr + +/* void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); */ + .global cpu_post_exec_11 +cpu_post_exec_11: + mflr r0 + stwu r0, -4(r1) + stwu r4, -4(r1) + + mtlr r3 + mr r3, r5 + blrl + + lwz r4, 0(r1) + stw r3, 0(r4) + + lwz r0, 4(r1) + addi r1, r1, 8 + mtlr r0 + blr + +/* void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1); */ + .global cpu_post_exec_21 +cpu_post_exec_21: + mflr r0 + stwu r0, -4(r1) + stwu r4, -4(r1) + stwu r5, -4(r1) + + li r0, 0 + mtxer r0 + lwz r0, 0(r4) + mtcr r0 + + mtlr r3 + mr r3, r6 + blrl + + mfcr r0 + lwz r4, 4(r1) + stw r0, 0(r4) + lwz r4, 0(r1) + stw r3, 0(r4) + + lwz r0, 8(r1) + addi r1, r1, 12 + mtlr r0 + blr + +/* void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1, + ulong op2); */ + .global cpu_post_exec_22 +cpu_post_exec_22: + mflr r0 + stwu r0, -4(r1) + stwu r4, -4(r1) + stwu r5, -4(r1) + + li r0, 0 + mtxer r0 + lwz r0, 0(r4) + mtcr r0 + + mtlr r3 + mr r3, r6 + mr r4, r7 + blrl + + mfcr r0 + lwz r4, 4(r1) + stw r0, 0(r4) + lwz r4, 0(r1) + stw r3, 0(r4) + + lwz r0, 8(r1) + addi r1, r1, 12 + mtlr r0 + blr + +/* void cpu_post_exec_12w (ulong *code, ulong *op1, ulong op2, ulong op3); */ + .global cpu_post_exec_12w +cpu_post_exec_12w: + mflr r0 + stwu r0, -4(r1) + stwu r4, -4(r1) + + mtlr r3 + lwz r3, 0(r4) + mr r4, r5 + mr r5, r6 + blrl + + lwz r4, 0(r1) + stw r3, 0(r4) + + lwz r0, 4(r1) + addi r1, r1, 8 + mtlr r0 + blr + +/* void cpu_post_exec_11w (ulong *code, ulong *op1, ulong op2); */ + .global cpu_post_exec_11w +cpu_post_exec_11w: + mflr r0 + stwu r0, -4(r1) + stwu r4, -4(r1) + + mtlr r3 + lwz r3, 0(r4) + mr r4, r5 + blrl + + lwz r4, 0(r1) + stw r3, 0(r4) + + lwz r0, 4(r1) + addi r1, r1, 8 + mtlr r0 + blr + +/* void cpu_post_exec_22w (ulong *code, ulong *op1, ulong op2, ulong *op3); */ + .global cpu_post_exec_22w +cpu_post_exec_22w: + mflr r0 + stwu r0, -4(r1) + stwu r4, -4(r1) + stwu r6, -4(r1) + + mtlr r3 + lwz r3, 0(r4) + mr r4, r5 + blrl + + lwz r4, 4(r1) + stw r3, 0(r4) + lwz r4, 0(r1) + stw r5, 0(r4) + + lwz r0, 8(r1) + addi r1, r1, 12 + mtlr r0 + blr + +/* void cpu_post_exec_21w (ulong *code, ulong *op1, ulong *op2); */ + .global cpu_post_exec_21w +cpu_post_exec_21w: + mflr r0 + stwu r0, -4(r1) + stwu r4, -4(r1) + stwu r5, -4(r1) + + mtlr r3 + lwz r3, 0(r4) + blrl + + lwz r5, 4(r1) + stw r3, 0(r5) + lwz r5, 0(r1) + stw r4, 0(r5) + + lwz r0, 8(r1) + addi r1, r1, 12 + mtlr r0 + blr + +/* void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3); */ + .global cpu_post_exec_21x +cpu_post_exec_21x: + mflr r0 + stwu r0, -4(r1) + stwu r4, -4(r1) + stwu r5, -4(r1) + + mtlr r3 + mr r3, r6 + blrl + + lwz r5, 4(r1) + stw r3, 0(r5) + lwz r5, 0(r1) + stw r4, 0(r5) + + lwz r0, 8(r1) + addi r1, r1, 12 + mtlr r0 + blr + +/* void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump, + ulong cr); */ + .global cpu_post_exec_31 +cpu_post_exec_31: + mflr r0 + stwu r0, -4(r1) + stwu r4, -4(r1) + stwu r5, -4(r1) + stwu r6, -4(r1) + + mtlr r3 + lwz r3, 0(r4) + lwz r4, 0(r5) + mr r6, r7 + blrl + + lwz r7, 8(r1) + stw r3, 0(r7) + lwz r7, 4(r1) + stw r4, 0(r7) + lwz r7, 0(r1) + stw r5, 0(r7) + + lwz r0, 12(r1) + addi r1, r1, 16 + mtlr r0 + blr + +/* int cpu_post_complex_1_asm (int a1, int a2, int a3, int a4, int n); */ + .global cpu_post_complex_1_asm +cpu_post_complex_1_asm: + li r9,0 + cmpw r9,r7 + bge cpu_post_complex_1_done + mtctr r7 +cpu_post_complex_1_loop: + mullw r0,r3,r4 + subf r0,r5,r0 + divw r0,r0,r6 + add r9,r9,r0 + bdnz cpu_post_complex_1_loop +cpu_post_complex_1_done: + mr r3,r9 + blr + +/* int cpu_post_complex_2_asm (int x, int n); */ + .global cpu_post_complex_2_asm +cpu_post_complex_2_asm: + mr. r0,r4 + mtctr r0 + mr r0,r3 + li r3,1 + li r4,1 + blelr +cpu_post_complex_2_loop: + mullw r3,r3,r0 + add r3,r3,r4 + bdnz cpu_post_complex_2_loop +blr + +#endif +#endif diff --git a/post/lib_ppc/b.c b/post/lib_ppc/b.c new file mode 100644 index 00000000000..b4b17c8ff07 --- /dev/null +++ b/post/lib_ppc/b.c @@ -0,0 +1,197 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Branch instructions: b, bl, bc + * + * The first 2 instructions (b, bl) are verified by jumping + * to a fixed address and checking whether control was transfered + * to that very point. For the bl instruction the value of the + * link register is checked as well (using mfspr). + * To verify the bc instruction various combinations of the BI/BO + * fields, the CTR and the condition register values are + * checked. The list of such combinations is pre-built and + * linked in U-Boot at build time. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); +extern void cpu_post_exec_31 (ulong *code, ulong *ctr, ulong *lr, ulong *jump, + ulong cr); + +static int cpu_post_test_bc (ulong cmd, ulong bo, ulong bi, + int pjump, int dec, int link, ulong pctr, ulong cr) +{ + int ret = 0; + ulong lr = 0; + ulong ctr = pctr; + ulong jump; + + unsigned long code[] = + { + ASM_MTCR(6), + ASM_MFLR(6), + ASM_MTCTR(3), + ASM_MTLR(4), + ASM_LI(5, 1), + ASM_3O(cmd, bo, bi, 8), + ASM_LI(5, 0), + ASM_MFCTR(3), + ASM_MFLR(4), + ASM_MTLR(6), + ASM_BLR, + }; + + cpu_post_exec_31 (code, &ctr, &lr, &jump, cr); + + if (ret == 0) + ret = pjump == jump ? 0 : -1; + if (ret == 0) + { + if (dec) + ret = pctr == ctr + 1 ? 0 : -1; + else + ret = pctr == ctr ? 0 : -1; + } + if (ret == 0) + { + if (link) + ret = lr == (ulong) code + 24 ? 0 : -1; + else + ret = lr == 0 ? 0 : -1; + } + + return ret; +} + +int cpu_post_test_b (void) +{ + int ret = 0; + unsigned int i; + + if (ret == 0) + { + ulong code[] = + { + ASM_MFLR(4), + ASM_MTLR(3), + ASM_B(4), + ASM_MFLR(3), + ASM_MTLR(4), + ASM_BLR, + }; + ulong res; + + cpu_post_exec_11 (code, &res, 0); + + ret = res == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at b1 test !\n"); + } + } + + if (ret == 0) + { + ulong code[] = + { + ASM_MFLR(4), + ASM_MTLR(3), + ASM_BL(4), + ASM_MFLR(3), + ASM_MTLR(4), + ASM_BLR, + }; + ulong res; + + cpu_post_exec_11 (code, &res, 0); + + ret = res == (ulong)code + 12 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at b2 test !\n"); + } + } + + if (ret == 0) + { + ulong cc, cd; + int cond; + ulong ctr; + int link; + + i = 0; + + for (cc = 0; cc < 4 && ret == 0; cc++) + { + for (cd = 0; cd < 4 && ret == 0; cd++) + { + for (link = 0; link <= 1 && ret == 0; link++) + { + for (cond = 0; cond <= 1 && ret == 0; cond++) + { + for (ctr = 1; ctr <= 2 && ret == 0; ctr++) + { + int dec = cd < 2; + int cr = cond ? 0x80000000 : 0x00000000; + int jumpc = cc >= 2 || + (cc == 0 && !cond) || + (cc == 1 && cond); + int jumpd = cd >= 2 || + (cd == 0 && ctr != 1) || + (cd == 1 && ctr == 1); + int jump = jumpc && jumpd; + + ret = cpu_post_test_bc (link ? OP_BCL : OP_BC, + (cc << 3) + (cd << 1), 0, jump, dec, link, + ctr, cr); + + if (ret != 0) + { + post_log ("Error at b3 test %d !\n", i); + } + + i++; + } + } + } + } + } + } + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/cmp.c b/post/lib_ppc/cmp.c new file mode 100644 index 00000000000..789a24cb7f1 --- /dev/null +++ b/post/lib_ppc/cmp.c @@ -0,0 +1,133 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Integer compare instructions: cmpw, cmplw + * + * To verify these instructions the test runs them with + * different combinations of operands, reads the condition + * register value and compares it with the expected one. + * The test contains a pre-built table + * containing the description of each test case: the instruction, + * the values of the operands, the condition field to save + * the result in and the expected result. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_12 (ulong *code, ulong *res, ulong op1, ulong op2); + +static struct cpu_post_cmp_s +{ + ulong cmd; + ulong op1; + ulong op2; + ulong cr; + ulong res; +} cpu_post_cmp_table[] = +{ + { + OP_CMPW, + 123, + 123, + 2, + 0x02 + }, + { + OP_CMPW, + 123, + 133, + 3, + 0x08 + }, + { + OP_CMPW, + 123, + -133, + 4, + 0x04 + }, + { + OP_CMPLW, + 123, + 123, + 2, + 0x02 + }, + { + OP_CMPLW, + 123, + -133, + 3, + 0x08 + }, + { + OP_CMPLW, + 123, + 113, + 4, + 0x04 + }, +}; +static unsigned int cpu_post_cmp_size = + sizeof (cpu_post_cmp_table) / sizeof (struct cpu_post_cmp_s); + +int cpu_post_test_cmp (void) +{ + int ret = 0; + unsigned int i; + + for (i = 0; i < cpu_post_cmp_size && ret == 0; i++) + { + struct cpu_post_cmp_s *test = cpu_post_cmp_table + i; + unsigned long code[] = + { + ASM_2C(test->cmd, test->cr, 3, 4), + ASM_MFCR(3), + ASM_BLR + }; + ulong res; + + cpu_post_exec_12 (code, & res, test->op1, test->op2); + + ret = ((res >> (28 - 4 * test->cr)) & 0xe) == test->res ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at cmp test %d !\n", i); + } + } + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/cmpi.c b/post/lib_ppc/cmpi.c new file mode 100644 index 00000000000..e0c2aaff826 --- /dev/null +++ b/post/lib_ppc/cmpi.c @@ -0,0 +1,133 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Integer compare instructions: cmpwi, cmplwi + * + * To verify these instructions the test runs them with + * different combinations of operands, reads the condition + * register value and compares it with the expected one. + * The test contains a pre-built table + * containing the description of each test case: the instruction, + * the values of the operands, the condition field to save + * the result in and the expected result. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); + +static struct cpu_post_cmpi_s +{ + ulong cmd; + ulong op1; + ushort op2; + ulong cr; + ulong res; +} cpu_post_cmpi_table[] = +{ + { + OP_CMPWI, + 123, + 123, + 2, + 0x02 + }, + { + OP_CMPWI, + 123, + 133, + 3, + 0x08 + }, + { + OP_CMPWI, + 123, + -133, + 4, + 0x04 + }, + { + OP_CMPLWI, + 123, + 123, + 2, + 0x02 + }, + { + OP_CMPLWI, + 123, + -133, + 3, + 0x08 + }, + { + OP_CMPLWI, + 123, + 113, + 4, + 0x04 + }, +}; +static unsigned int cpu_post_cmpi_size = + sizeof (cpu_post_cmpi_table) / sizeof (struct cpu_post_cmpi_s); + +int cpu_post_test_cmpi (void) +{ + int ret = 0; + unsigned int i; + + for (i = 0; i < cpu_post_cmpi_size && ret == 0; i++) + { + struct cpu_post_cmpi_s *test = cpu_post_cmpi_table + i; + unsigned long code[] = + { + ASM_1IC(test->cmd, test->cr, 3, test->op2), + ASM_MFCR(3), + ASM_BLR + }; + ulong res; + + cpu_post_exec_11 (code, & res, test->op1); + + ret = ((res >> (28 - 4 * test->cr)) & 0xe) == test->res ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at cmpi test %d !\n", i); + } + } + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/complex.c b/post/lib_ppc/complex.c new file mode 100644 index 00000000000..033584bec08 --- /dev/null +++ b/post/lib_ppc/complex.c @@ -0,0 +1,126 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Complex calculations + * + * The calculations in this test are just a combination of simpler + * calculations, but probably under different timing conditions, etc. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern int cpu_post_complex_1_asm (int a1, int a2, int a3, int a4, int n); +extern int cpu_post_complex_2_asm (int x, int n); + + /* + * n + * SUM (a1 * a2 - a3) / a4 = n * result + * i=1 + */ +static int cpu_post_test_complex_1 (void) +{ + int a1 = 666; + int a2 = 667; + int a3 = 668; + int a4 = 66; + int n = 100; + int result = 6720; /* (a1 * a2 - a3) / a4 */ + + if (cpu_post_complex_1_asm(a1, a2, a3, a4, n) != n * result) + { + return -1; + } + + return 0; +} + + /* (1 + x + x^2 + ... + x^n) * (1 - x) = 1 - x^(n+1) + */ +static int cpu_post_test_complex_2 (void) +{ + int ret = -1; + int x; + int n; + int k; + int left; + int right; + + for (x = -8; x <= 8; x ++) + { + n = 9; + + left = cpu_post_complex_2_asm(x, n); + left *= 1 - x; + + right = 1; + for (k = 0; k <= n; k ++) + { + right *= x; + } + right = 1 - right; + + if (left != right) + { + goto Done; + } + } + + ret = 0; + Done: + + return ret; +} + +int cpu_post_test_complex (void) +{ + int ret = 0; + + if (ret == 0) + { + ret = cpu_post_test_complex_1(); + } + + if (ret == 0) + { + ret = cpu_post_test_complex_2(); + } + + if (ret != 0) + { + post_log ("Error at complex test !\n"); + } + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/cpu.c b/post/lib_ppc/cpu.c new file mode 100644 index 00000000000..1f2ded2bf26 --- /dev/null +++ b/post/lib_ppc/cpu.c @@ -0,0 +1,139 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * + * This test checks the arithmetic logic unit (ALU) of CPU. + * It tests independently various groups of instructions using + * run-time modification of the code to reduce the memory footprint. + * For more details refer to post/cpu/ *.c files. + */ + +#ifdef CONFIG_POST + +#include +#include + +#if CONFIG_POST & CFG_POST_CPU + +extern int cpu_post_test_cmp (void); +extern int cpu_post_test_cmpi (void); +extern int cpu_post_test_two (void); +extern int cpu_post_test_twox (void); +extern int cpu_post_test_three (void); +extern int cpu_post_test_threex (void); +extern int cpu_post_test_threei (void); +extern int cpu_post_test_andi (void); +extern int cpu_post_test_srawi (void); +extern int cpu_post_test_rlwnm (void); +extern int cpu_post_test_rlwinm (void); +extern int cpu_post_test_rlwimi (void); +extern int cpu_post_test_store (void); +extern int cpu_post_test_load (void); +extern int cpu_post_test_cr (void); +extern int cpu_post_test_b (void); +extern int cpu_post_test_multi (void); +extern int cpu_post_test_string (void); +extern int cpu_post_test_complex (void); + +ulong cpu_post_makecr (long v) +{ + ulong cr = 0; + + if (v < 0) + cr |= 0x80000000; + if (v > 0) + cr |= 0x40000000; + if (v == 0) + cr |= 0x20000000; + + return cr; +} + +int cpu_post_test (int flags) +{ + int ic = icache_status (); + int ret = 0; + + WATCHDOG_RESET(); + if (ic) + icache_disable (); + + if (ret == 0) + ret = cpu_post_test_cmp (); + if (ret == 0) + ret = cpu_post_test_cmpi (); + if (ret == 0) + ret = cpu_post_test_two (); + if (ret == 0) + ret = cpu_post_test_twox (); + WATCHDOG_RESET(); + if (ret == 0) + ret = cpu_post_test_three (); + if (ret == 0) + ret = cpu_post_test_threex (); + if (ret == 0) + ret = cpu_post_test_threei (); + if (ret == 0) + ret = cpu_post_test_andi (); + WATCHDOG_RESET(); + if (ret == 0) + ret = cpu_post_test_srawi (); + if (ret == 0) + ret = cpu_post_test_rlwnm (); + if (ret == 0) + ret = cpu_post_test_rlwinm (); + if (ret == 0) + ret = cpu_post_test_rlwimi (); + WATCHDOG_RESET(); + if (ret == 0) + ret = cpu_post_test_store (); + if (ret == 0) + ret = cpu_post_test_load (); + if (ret == 0) + ret = cpu_post_test_cr (); + if (ret == 0) + ret = cpu_post_test_b (); + WATCHDOG_RESET(); + if (ret == 0) + ret = cpu_post_test_multi (); + WATCHDOG_RESET(); + if (ret == 0) + ret = cpu_post_test_string (); + if (ret == 0) + ret = cpu_post_test_complex (); + WATCHDOG_RESET(); + + if (ic) + icache_enable (); + + WATCHDOG_RESET(); + + return ret; +} + +#endif /* CONFIG_POST & CFG_POST_CPU */ +#endif /* CONFIG_POST */ diff --git a/post/lib_ppc/cpu_asm.h b/post/lib_ppc/cpu_asm.h new file mode 100644 index 00000000000..1cbaf4121fe --- /dev/null +++ b/post/lib_ppc/cpu_asm.h @@ -0,0 +1,224 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ +#ifndef _CPU_ASM_H +#define _CPU_ASM_H + +#define BIT_C 0x00000001 + +#define OP_BLR 0x4e800020 +#define OP_EXTSB 0x7c000774 +#define OP_EXTSH 0x7c000734 +#define OP_NEG 0x7c0000d0 +#define OP_CNTLZW 0x7c000034 +#define OP_ADD 0x7c000214 +#define OP_ADDC 0x7c000014 +#define OP_ADDME 0x7c0001d4 +#define OP_ADDZE 0x7c000194 +#define OP_ADDE 0x7c000114 +#define OP_ADDI 0x38000000 +#define OP_SUBF 0x7c000050 +#define OP_SUBFC 0x7c000010 +#define OP_SUBFE 0x7c000110 +#define OP_SUBFME 0x7c0001d0 +#define OP_SUBFZE 0x7c000190 +#define OP_MFCR 0x7c000026 +#define OP_MTCR 0x7c0ff120 +#define OP_MFXER 0x7c0102a6 +#define OP_MTXER 0x7c0103a6 +#define OP_MCRXR 0x7c000400 +#define OP_MCRF 0x4c000000 +#define OP_CRAND 0x4c000202 +#define OP_CRANDC 0x4c000102 +#define OP_CROR 0x4c000382 +#define OP_CRORC 0x4c000342 +#define OP_CRXOR 0x4c000182 +#define OP_CRNAND 0x4c0001c2 +#define OP_CRNOR 0x4c000042 +#define OP_CREQV 0x4c000242 +#define OP_CMPW 0x7c000000 +#define OP_CMPLW 0x7c000040 +#define OP_CMPWI 0x2c000000 +#define OP_CMPLWI 0x28000000 +#define OP_MULLW 0x7c0001d6 +#define OP_MULHW 0x7c000096 +#define OP_MULHWU 0x7c000016 +#define OP_DIVW 0x7c0003d6 +#define OP_DIVWU 0x7c000396 +#define OP_OR 0x7c000378 +#define OP_ORC 0x7c000338 +#define OP_XOR 0x7c000278 +#define OP_NAND 0x7c0003b8 +#define OP_NOR 0x7c0000f8 +#define OP_EQV 0x7c000238 +#define OP_SLW 0x7c000030 +#define OP_SRW 0x7c000430 +#define OP_SRAW 0x7c000630 +#define OP_ORI 0x60000000 +#define OP_ORIS 0x64000000 +#define OP_XORI 0x68000000 +#define OP_XORIS 0x6c000000 +#define OP_ANDI_ 0x70000000 +#define OP_ANDIS_ 0x74000000 +#define OP_SRAWI 0x7c000670 +#define OP_RLWINM 0x54000000 +#define OP_RLWNM 0x5c000000 +#define OP_RLWIMI 0x50000000 +#define OP_LWZ 0x80000000 +#define OP_LHZ 0xa0000000 +#define OP_LHA 0xa8000000 +#define OP_LBZ 0x88000000 +#define OP_LWZU 0x84000000 +#define OP_LHZU 0xa4000000 +#define OP_LHAU 0xac000000 +#define OP_LBZU 0x8c000000 +#define OP_LWZX 0x7c00002e +#define OP_LHZX 0x7c00022e +#define OP_LHAX 0x7c0002ae +#define OP_LBZX 0x7c0000ae +#define OP_LWZUX 0x7c00006e +#define OP_LHZUX 0x7c00026e +#define OP_LHAUX 0x7c0002ee +#define OP_LBZUX 0x7c0000ee +#define OP_STW 0x90000000 +#define OP_STH 0xb0000000 +#define OP_STB 0x98000000 +#define OP_STWU 0x94000000 +#define OP_STHU 0xb4000000 +#define OP_STBU 0x9c000000 +#define OP_STWX 0x7c00012e +#define OP_STHX 0x7c00032e +#define OP_STBX 0x7c0001ae +#define OP_STWUX 0x7c00016e +#define OP_STHUX 0x7c00036e +#define OP_STBUX 0x7c0001ee +#define OP_B 0x48000000 +#define OP_BL 0x48000001 +#define OP_BC 0x40000000 +#define OP_BCL 0x40000001 +#define OP_MTLR 0x7c0803a6 +#define OP_MFLR 0x7c0802a6 +#define OP_MTCTR 0x7c0903a6 +#define OP_MFCTR 0x7c0902a6 +#define OP_LMW 0xb8000000 +#define OP_STMW 0xbc000000 +#define OP_LSWI 0x7c0004aa +#define OP_LSWX 0x7c00042a +#define OP_STSWI 0x7c0005aa +#define OP_STSWX 0x7c00052a + +#define ASM_0(opcode) (opcode) +#define ASM_1(opcode, rd) ((opcode) + \ + ((rd) << 21)) +#define ASM_1C(opcode, cr) ((opcode) + \ + ((cr) << 23)) +#define ASM_11(opcode, rd, rs) ((opcode) + \ + ((rd) << 21) + \ + ((rs) << 16)) +#define ASM_11C(opcode, cd, cs) ((opcode) + \ + ((cd) << 23) + \ + ((cs) << 18)) +#define ASM_11X(opcode, rd, rs) ((opcode) + \ + ((rs) << 21) + \ + ((rd) << 16)) +#define ASM_11I(opcode, rd, rs, simm) ((opcode) + \ + ((rd) << 21) + \ + ((rs) << 16) + \ + ((simm) & 0xffff)) +#define ASM_11IF(opcode, rd, rs, simm) ((opcode) + \ + ((rd) << 21) + \ + ((rs) << 16) + \ + ((simm) << 11)) +#define ASM_11S(opcode, rd, rs, sh) ((opcode) + \ + ((rs) << 21) + \ + ((rd) << 16) + \ + ((sh) << 11)) +#define ASM_11IX(opcode, rd, rs, imm) ((opcode) + \ + ((rs) << 21) + \ + ((rd) << 16) + \ + ((imm) & 0xffff)) +#define ASM_12(opcode, rd, rs1, rs2) ((opcode) + \ + ((rd) << 21) + \ + ((rs1) << 16) + \ + ((rs2) << 11)) +#define ASM_12F(opcode, fd, fs1, fs2) ((opcode) + \ + ((fd) << 21) + \ + ((fs1) << 16) + \ + ((fs2) << 11)) +#define ASM_12X(opcode, rd, rs1, rs2) ((opcode) + \ + ((rs1) << 21) + \ + ((rd) << 16) + \ + ((rs2) << 11)) +#define ASM_2C(opcode, cr, rs1, rs2) ((opcode) + \ + ((cr) << 23) + \ + ((rs1) << 16) + \ + ((rs2) << 11)) +#define ASM_1IC(opcode, cr, rs, imm) ((opcode) + \ + ((cr) << 23) + \ + ((rs) << 16) + \ + ((imm) & 0xffff)) +#define ASM_122(opcode, rd, rs1, rs2, imm1, imm2) \ + ((opcode) + \ + ((rs1) << 21) + \ + ((rd) << 16) + \ + ((rs2) << 11) + \ + ((imm1) << 6) + \ + ((imm2) << 1)) +#define ASM_113(opcode, rd, rs, imm1, imm2, imm3) \ + ((opcode) + \ + ((rs) << 21) + \ + ((rd) << 16) + \ + ((imm1) << 11) + \ + ((imm2) << 6) + \ + ((imm3) << 1)) +#define ASM_1O(opcode, off) ((opcode) + (off)) +#define ASM_3O(opcode, bo, bi, off) ((opcode) + \ + ((bo) << 21) + \ + ((bi) << 16) + \ + (off)) + +#define ASM_ADDI(rd, rs, simm) ASM_11I(OP_ADDI, rd, rs, simm) +#define ASM_BLR ASM_0(OP_BLR) +#define ASM_STW(rd, rs, simm) ASM_11I(OP_STW, rd, rs, simm) +#define ASM_LWZ(rd, rs, simm) ASM_11I(OP_LWZ, rd, rs, simm) +#define ASM_MFCR(rd) ASM_1(OP_MFCR, rd) +#define ASM_MTCR(rd) ASM_1(OP_MTCR, rd) +#define ASM_MFXER(rd) ASM_1(OP_MFXER, rd) +#define ASM_MTXER(rd) ASM_1(OP_MTXER, rd) +#define ASM_MFCTR(rd) ASM_1(OP_MFCTR, rd) +#define ASM_MTCTR(rd) ASM_1(OP_MTCTR, rd) +#define ASM_MCRXR(cr) ASM_1C(OP_MCRXR, cr) +#define ASM_MCRF(cd, cs) ASM_11C(OP_MCRF, cd, cs) +#define ASM_B(off) ASM_1O(OP_B, off) +#define ASM_BL(off) ASM_1O(OP_BL, off) +#define ASM_MFLR(rd) ASM_1(OP_MFLR, rd) +#define ASM_MTLR(rd) ASM_1(OP_MTLR, rd) +#define ASM_LI(rd, imm) ASM_ADDI(rd, 0, imm) +#define ASM_LMW(rd, rs, simm) ASM_11I(OP_LMW, rd, rs, simm) +#define ASM_STMW(rd, rs, simm) ASM_11I(OP_STMW, rd, rs, simm) +#define ASM_LSWI(rd, rs, simm) ASM_11IF(OP_LSWI, rd, rs, simm) +#define ASM_LSWX(rd, rs1, rs2) ASM_12(OP_LSWX, rd, rs1, rs2) +#define ASM_STSWI(rd, rs, simm) ASM_11IF(OP_STSWI, rd, rs, simm) +#define ASM_STSWX(rd, rs1, rs2) ASM_12(OP_STSWX, rd, rs1, rs2) + + +#endif /* _CPU_ASM_H */ diff --git a/post/lib_ppc/cr.c b/post/lib_ppc/cr.c new file mode 100644 index 00000000000..da6ef3745d0 --- /dev/null +++ b/post/lib_ppc/cr.c @@ -0,0 +1,356 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Condition register istructions: mtcr, mfcr, mcrxr, + * crand, crandc, cror, crorc, crxor, + * crnand, crnor, creqv, mcrf + * + * The mtcrf/mfcr instructions is tested by loading different + * values into the condition register (mtcrf), moving its value + * to a general-purpose register (mfcr) and comparing this value + * with the expected one. + * The mcrxr instruction is tested by loading a fixed value + * into the XER register (mtspr), moving XER value to the + * condition register (mcrxr), moving it to a general-purpose + * register (mfcr) and comparing the value of this register with + * the expected one. + * The rest of instructions is tested by loading a fixed + * value into the condition register (mtcrf), executing each + * instruction several times to modify all 4-bit condition + * fields, moving the value of the conditional register to a + * general-purpose register (mfcr) and comparing it with the + * expected one. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_11 (ulong *code, ulong *res, ulong op1); +extern void cpu_post_exec_21x (ulong *code, ulong *op1, ulong *op2, ulong op3); + +static ulong cpu_post_cr_table1[] = +{ + 0xaaaaaaaa, + 0x55555555, +}; +static unsigned int cpu_post_cr_size1 = + sizeof (cpu_post_cr_table1) / sizeof (ulong); + +static struct cpu_post_cr_s2 { + ulong xer; + ulong cr; +} cpu_post_cr_table2[] = +{ + { + 0xa0000000, + 1 + }, + { + 0x40000000, + 5 + }, +}; +static unsigned int cpu_post_cr_size2 = + sizeof (cpu_post_cr_table2) / sizeof (struct cpu_post_cr_s2); + +static struct cpu_post_cr_s3 { + ulong cr; + ulong cs; + ulong cd; + ulong res; +} cpu_post_cr_table3[] = +{ + { + 0x01234567, + 0, + 4, + 0x01230567 + }, + { + 0x01234567, + 7, + 0, + 0x71234567 + }, +}; +static unsigned int cpu_post_cr_size3 = + sizeof (cpu_post_cr_table3) / sizeof (struct cpu_post_cr_s3); + +static struct cpu_post_cr_s4 { + ulong cmd; + ulong cr; + ulong op1; + ulong op2; + ulong op3; + ulong res; +} cpu_post_cr_table4[] = +{ + { + OP_CRAND, + 0x0000ffff, + 0, + 16, + 0, + 0x0000ffff + }, + { + OP_CRAND, + 0x0000ffff, + 16, + 17, + 0, + 0x8000ffff + }, + { + OP_CRANDC, + 0x0000ffff, + 0, + 16, + 0, + 0x0000ffff + }, + { + OP_CRANDC, + 0x0000ffff, + 16, + 0, + 0, + 0x8000ffff + }, + { + OP_CROR, + 0x0000ffff, + 0, + 16, + 0, + 0x8000ffff + }, + { + OP_CROR, + 0x0000ffff, + 0, + 1, + 0, + 0x0000ffff + }, + { + OP_CRORC, + 0x0000ffff, + 0, + 16, + 0, + 0x0000ffff + }, + { + OP_CRORC, + 0x0000ffff, + 0, + 0, + 0, + 0x8000ffff + }, + { + OP_CRXOR, + 0x0000ffff, + 0, + 0, + 0, + 0x0000ffff + }, + { + OP_CRXOR, + 0x0000ffff, + 0, + 16, + 0, + 0x8000ffff + }, + { + OP_CRNAND, + 0x0000ffff, + 0, + 16, + 0, + 0x8000ffff + }, + { + OP_CRNAND, + 0x0000ffff, + 16, + 17, + 0, + 0x0000ffff + }, + { + OP_CRNOR, + 0x0000ffff, + 0, + 16, + 0, + 0x0000ffff + }, + { + OP_CRNOR, + 0x0000ffff, + 0, + 1, + 0, + 0x8000ffff + }, + { + OP_CREQV, + 0x0000ffff, + 0, + 0, + 0, + 0x8000ffff + }, + { + OP_CREQV, + 0x0000ffff, + 0, + 16, + 0, + 0x0000ffff + }, +}; +static unsigned int cpu_post_cr_size4 = + sizeof (cpu_post_cr_table4) / sizeof (struct cpu_post_cr_s4); + +int cpu_post_test_cr (void) +{ + int ret = 0; + unsigned int i; + unsigned long cr_sav; + + asm ( "mfcr %0" : "=r" (cr_sav) : ); + + for (i = 0; i < cpu_post_cr_size1 && ret == 0; i++) + { + ulong cr = cpu_post_cr_table1[i]; + ulong res; + + unsigned long code[] = + { + ASM_MTCR(3), + ASM_MFCR(3), + ASM_BLR, + }; + + cpu_post_exec_11 (code, &res, cr); + + ret = res == cr ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at cr1 test %d !\n", i); + } + } + + for (i = 0; i < cpu_post_cr_size2 && ret == 0; i++) + { + struct cpu_post_cr_s2 *test = cpu_post_cr_table2 + i; + ulong res; + ulong xer; + + unsigned long code[] = + { + ASM_MTXER(3), + ASM_MCRXR(test->cr), + ASM_MFCR(3), + ASM_MFXER(4), + ASM_BLR, + }; + + cpu_post_exec_21x (code, &res, &xer, test->xer); + + ret = xer == 0 && ((res << (4 * test->cr)) & 0xe0000000) == test->xer ? + 0 : -1; + + if (ret != 0) + { + post_log ("Error at cr2 test %d !\n", i); + } + } + + for (i = 0; i < cpu_post_cr_size3 && ret == 0; i++) + { + struct cpu_post_cr_s3 *test = cpu_post_cr_table3 + i; + ulong res; + + unsigned long code[] = + { + ASM_MTCR(3), + ASM_MCRF(test->cd, test->cs), + ASM_MFCR(3), + ASM_BLR, + }; + + cpu_post_exec_11 (code, &res, test->cr); + + ret = res == test->res ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at cr3 test %d !\n", i); + } + } + + for (i = 0; i < cpu_post_cr_size4 && ret == 0; i++) + { + struct cpu_post_cr_s4 *test = cpu_post_cr_table4 + i; + ulong res; + + unsigned long code[] = + { + ASM_MTCR(3), + ASM_12F(test->cmd, test->op3, test->op1, test->op2), + ASM_MFCR(3), + ASM_BLR, + }; + + cpu_post_exec_11 (code, &res, test->cr); + + ret = res == test->res ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at cr4 test %d !\n", i); + } + } + + asm ( "mtcr %0" : : "r" (cr_sav)); + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/load.c b/post/lib_ppc/load.c new file mode 100644 index 00000000000..393c56830d9 --- /dev/null +++ b/post/lib_ppc/load.c @@ -0,0 +1,255 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Load instructions: lbz(x)(u), lhz(x)(u), lha(x)(u), lwz(x)(u) + * + * All operations are performed on a 16-byte array. The array + * is 4-byte aligned. The base register points to offset 8. + * The immediate offset (index register) ranges in [-8 ... +7]. + * The test cases are composed so that they do not + * cause alignment exceptions. + * The test contains a pre-built table describing all test cases. + * The table entry contains: + * the instruction opcode, the array contents, the value of the index + * register and the expected value of the destination register. + * After executing the instruction, the test verifies the + * value of the destination register and the value of the base + * register (it must change for "load with update" instructions). + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_22w (ulong *code, ulong *op1, ulong op2, ulong *op3); +extern void cpu_post_exec_21w (ulong *code, ulong *op1, ulong *op2); + +static struct cpu_post_load_s +{ + ulong cmd; + uint width; + int update; + int index; + ulong offset; +} cpu_post_load_table[] = +{ + { + OP_LWZ, + 4, + 0, + 0, + 4 + }, + { + OP_LHA, + 3, + 0, + 0, + 2 + }, + { + OP_LHZ, + 2, + 0, + 0, + 2 + }, + { + OP_LBZ, + 1, + 0, + 0, + 1 + }, + { + OP_LWZU, + 4, + 1, + 0, + 4 + }, + { + OP_LHAU, + 3, + 1, + 0, + 2 + }, + { + OP_LHZU, + 2, + 1, + 0, + 2 + }, + { + OP_LBZU, + 1, + 1, + 0, + 1 + }, + { + OP_LWZX, + 4, + 0, + 1, + 4 + }, + { + OP_LHAX, + 3, + 0, + 1, + 2 + }, + { + OP_LHZX, + 2, + 0, + 1, + 2 + }, + { + OP_LBZX, + 1, + 0, + 1, + 1 + }, + { + OP_LWZUX, + 4, + 1, + 1, + 4 + }, + { + OP_LHAUX, + 3, + 1, + 1, + 2 + }, + { + OP_LHZUX, + 2, + 1, + 1, + 2 + }, + { + OP_LBZUX, + 1, + 1, + 1, + 1 + }, +}; +static unsigned int cpu_post_load_size = + sizeof (cpu_post_load_table) / sizeof (struct cpu_post_load_s); + +int cpu_post_test_load (void) +{ + int ret = 0; + unsigned int i; + + for (i = 0; i < cpu_post_load_size && ret == 0; i++) + { + struct cpu_post_load_s *test = cpu_post_load_table + i; + uchar data[16] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + ulong base0 = (ulong) (data + 8); + ulong base = base0; + ulong value; + + if (test->index) + { + ulong code[] = + { + ASM_12(test->cmd, 5, 3, 4), + ASM_BLR, + }; + + cpu_post_exec_22w (code, &base, test->offset, &value); + } + else + { + ulong code[] = + { + ASM_11I(test->cmd, 4, 3, test->offset), + ASM_BLR, + }; + + cpu_post_exec_21w (code, &base, &value); + } + + if (ret == 0) + { + if (test->update) + ret = base == base0 + test->offset ? 0 : -1; + else + ret = base == base0 ? 0 : -1; + } + + if (ret == 0) + { + switch (test->width) + { + case 1: + ret = *(uchar *)(base0 + test->offset) == value ? + 0 : -1; + break; + case 2: + ret = *(ushort *)(base0 + test->offset) == value ? + 0 : -1; + break; + case 3: + ret = *(short *)(base0 + test->offset) == value ? + 0 : -1; + break; + case 4: + ret = *(ulong *)(base0 + test->offset) == value ? + 0 : -1; + break; + } + } + + if (ret != 0) + { + post_log ("Error at load test %d !\n", i); + } + } + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/multi.c b/post/lib_ppc/multi.c new file mode 100644 index 00000000000..872438478fe --- /dev/null +++ b/post/lib_ppc/multi.c @@ -0,0 +1,81 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Load/store multiple word instructions: lmw, stmw + * + * 26 consecutive words are loaded from a source memory buffer + * into GPRs r6 through r31. After that, 26 consecutive words are stored + * from the GPRs r6 through r31 into a target memory buffer. The contents + * of the source and target buffers are then compared. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2); + +int cpu_post_test_multi (void) +{ + int ret = 0; + unsigned int i; + + if (ret == 0) + { + ulong src [26], dst [26]; + + ulong code[] = + { + ASM_LMW(5, 3, 0), + ASM_STMW(5, 4, 0), + ASM_BLR, + }; + + for (i = 0; i < sizeof(src) / sizeof(src[0]); i ++) + { + src[i] = i; + dst[i] = 0; + } + + cpu_post_exec_02(code, (ulong)src, (ulong)dst); + + ret = memcmp(src, dst, sizeof(dst)) == 0 ? 0 : -1; + } + + if (ret != 0) + { + post_log ("Error at multi test !\n"); + } + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/rlwimi.c b/post/lib_ppc/rlwimi.c new file mode 100644 index 00000000000..f65f79a8e84 --- /dev/null +++ b/post/lib_ppc/rlwimi.c @@ -0,0 +1,162 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Shift instructions: rlwimi + * + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1, + ulong op2); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_rlwimi_s +{ + ulong cmd; + ulong op0; + ulong op1; + uchar op2; + uchar mb; + uchar me; + ulong res; +} cpu_post_rlwimi_table[] = +{ + { + OP_RLWIMI, + 0xff00ffff, + 0x0000aa00, + 8, + 8, + 15, + 0xffaaffff + }, +}; +static unsigned int cpu_post_rlwimi_size = + sizeof (cpu_post_rlwimi_table) / sizeof (struct cpu_post_rlwimi_s); + +int cpu_post_test_rlwimi (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_rlwimi_size && ret == 0; i++) + { + struct cpu_post_rlwimi_s *test = cpu_post_rlwimi_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -20), + ASM_STW(3, stk, 8), + ASM_STW(4, stk, 12), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg1, stk, 8), + ASM_LWZ(reg0, stk, 12), + ASM_113(test->cmd, reg1, reg0, test->op2, test->mb, test->me), + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 20), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + unsigned long codecr[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -20), + ASM_STW(3, stk, 8), + ASM_STW(4, stk, 12), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg1, stk, 8), + ASM_LWZ(reg0, stk, 12), + ASM_113(test->cmd, reg1, reg0, test->op2, test->mb, test->me) | + BIT_C, + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 20), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + if (ret == 0) + { + cr = 0; + cpu_post_exec_22 (code, & cr, & res, test->op0, test->op1); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at rlwimi test %d !\n", i); + } + } + + if (ret == 0) + { + cpu_post_exec_22 (codecr, & cr, & res, test->op0, test->op1); + + ret = res == test->res && + (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at rlwimi test %d !\n", i); + } + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/rlwinm.c b/post/lib_ppc/rlwinm.c new file mode 100644 index 00000000000..e240c41b1a4 --- /dev/null +++ b/post/lib_ppc/rlwinm.c @@ -0,0 +1,155 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Shift instructions: rlwinm + * + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_rlwinm_s +{ + ulong cmd; + ulong op1; + uchar op2; + uchar mb; + uchar me; + ulong res; +} cpu_post_rlwinm_table[] = +{ + { + OP_RLWINM, + 0xffff0000, + 24, + 16, + 23, + 0x0000ff00 + }, +}; +static unsigned int cpu_post_rlwinm_size = + sizeof (cpu_post_rlwinm_table) / sizeof (struct cpu_post_rlwinm_s); + +int cpu_post_test_rlwinm (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_rlwinm_size && ret == 0; i++) + { + struct cpu_post_rlwinm_s *test = cpu_post_rlwinm_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_113(test->cmd, reg1, reg0, test->op2, test->mb, test->me), + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + unsigned long codecr[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_113(test->cmd, reg1, reg0, test->op2, test->mb, + test->me) | BIT_C, + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + if (ret == 0) + { + cr = 0; + cpu_post_exec_21 (code, & cr, & res, test->op1); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at rlwinm test %d !\n", i); + } + } + + if (ret == 0) + { + cpu_post_exec_21 (codecr, & cr, & res, test->op1); + + ret = res == test->res && + (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at rlwinm test %d !\n", i); + } + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/rlwnm.c b/post/lib_ppc/rlwnm.c new file mode 100644 index 00000000000..523cf4da59b --- /dev/null +++ b/post/lib_ppc/rlwnm.c @@ -0,0 +1,165 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Shift instructions: rlwnm + * + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1, + ulong op2); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_rlwnm_s +{ + ulong cmd; + ulong op1; + ulong op2; + uchar mb; + uchar me; + ulong res; +} cpu_post_rlwnm_table[] = +{ + { + OP_RLWNM, + 0xffff0000, + 24, + 16, + 23, + 0x0000ff00 + }, +}; +static unsigned int cpu_post_rlwnm_size = + sizeof (cpu_post_rlwnm_table) / sizeof (struct cpu_post_rlwnm_s); + +int cpu_post_test_rlwnm (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_rlwnm_size && ret == 0; i++) + { + struct cpu_post_rlwnm_s *test = cpu_post_rlwnm_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int reg2 = (reg + 2) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -24), + ASM_STW(3, stk, 12), + ASM_STW(4, stk, 16), + ASM_STW(reg0, stk, 8), + ASM_STW(reg1, stk, 4), + ASM_STW(reg2, stk, 0), + ASM_LWZ(reg1, stk, 12), + ASM_LWZ(reg0, stk, 16), + ASM_122(test->cmd, reg2, reg1, reg0, test->mb, test->me), + ASM_STW(reg2, stk, 12), + ASM_LWZ(reg2, stk, 0), + ASM_LWZ(reg1, stk, 4), + ASM_LWZ(reg0, stk, 8), + ASM_LWZ(3, stk, 12), + ASM_ADDI(1, stk, 24), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + unsigned long codecr[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -24), + ASM_STW(3, stk, 12), + ASM_STW(4, stk, 16), + ASM_STW(reg0, stk, 8), + ASM_STW(reg1, stk, 4), + ASM_STW(reg2, stk, 0), + ASM_LWZ(reg1, stk, 12), + ASM_LWZ(reg0, stk, 16), + ASM_122(test->cmd, reg2, reg1, reg0, test->mb, test->me) | + BIT_C, + ASM_STW(reg2, stk, 12), + ASM_LWZ(reg2, stk, 0), + ASM_LWZ(reg1, stk, 4), + ASM_LWZ(reg0, stk, 8), + ASM_LWZ(3, stk, 12), + ASM_ADDI(1, stk, 24), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + if (ret == 0) + { + cr = 0; + cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at rlwnm test %d !\n", i); + } + } + + if (ret == 0) + { + cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2); + + ret = res == test->res && + (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at rlwnm test %d !\n", i); + } + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/srawi.c b/post/lib_ppc/srawi.c new file mode 100644 index 00000000000..91c82c915f7 --- /dev/null +++ b/post/lib_ppc/srawi.c @@ -0,0 +1,156 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Shift instructions: srawi + * + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_srawi_s +{ + ulong cmd; + ulong op1; + uchar op2; + ulong res; +} cpu_post_srawi_table[] = +{ + { + OP_SRAWI, + 0x8000, + 3, + 0x1000 + }, + { + OP_SRAWI, + 0x80000000, + 3, + 0xf0000000 + }, +}; +static unsigned int cpu_post_srawi_size = + sizeof (cpu_post_srawi_table) / sizeof (struct cpu_post_srawi_s); + +int cpu_post_test_srawi (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_srawi_size && ret == 0; i++) + { + struct cpu_post_srawi_s *test = cpu_post_srawi_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_11S(test->cmd, reg1, reg0, test->op2), + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + unsigned long codecr[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_11S(test->cmd, reg1, reg0, test->op2) | BIT_C, + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + if (ret == 0) + { + cr = 0; + cpu_post_exec_21 (code, & cr, & res, test->op1); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at srawi test %d !\n", i); + } + } + + if (ret == 0) + { + cpu_post_exec_21 (codecr, & cr, & res, test->op1); + + ret = res == test->res && + (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at srawi test %d !\n", i); + } + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/store.c b/post/lib_ppc/store.c new file mode 100644 index 00000000000..f495bf2aab1 --- /dev/null +++ b/post/lib_ppc/store.c @@ -0,0 +1,235 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Store instructions: stb(x)(u), sth(x)(u), stw(x)(u) + * + * All operations are performed on a 16-byte array. The array + * is 4-byte aligned. The base register points to offset 8. + * The immediate offset (index register) ranges in [-8 ... +7]. + * The test cases are composed so that they do not + * cause alignment exceptions. + * The test contains a pre-built table describing all test cases. + * The table entry contains: + * the instruction opcode, the value of the index register and + * the value of the source register. After executing the + * instruction, the test verifies the contents of the array + * and the value of the base register (it must change for "store + * with update" instructions). + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_12w (ulong *code, ulong *op1, ulong op2, ulong op3); +extern void cpu_post_exec_11w (ulong *code, ulong *op1, ulong op2); + +static struct cpu_post_store_s +{ + ulong cmd; + uint width; + int update; + int index; + ulong offset; + ulong value; +} cpu_post_store_table[] = +{ + { + OP_STW, + 4, + 0, + 0, + -4, + 0xff00ff00 + }, + { + OP_STH, + 2, + 0, + 0, + -2, + 0xff00 + }, + { + OP_STB, + 1, + 0, + 0, + -1, + 0xff + }, + { + OP_STWU, + 4, + 1, + 0, + -4, + 0xff00ff00 + }, + { + OP_STHU, + 2, + 1, + 0, + -2, + 0xff00 + }, + { + OP_STBU, + 1, + 1, + 0, + -1, + 0xff + }, + { + OP_STWX, + 4, + 0, + 1, + -4, + 0xff00ff00 + }, + { + OP_STHX, + 2, + 0, + 1, + -2, + 0xff00 + }, + { + OP_STBX, + 1, + 0, + 1, + -1, + 0xff + }, + { + OP_STWUX, + 4, + 1, + 1, + -4, + 0xff00ff00 + }, + { + OP_STHUX, + 2, + 1, + 1, + -2, + 0xff00 + }, + { + OP_STBUX, + 1, + 1, + 1, + -1, + 0xff + }, +}; +static unsigned int cpu_post_store_size = + sizeof (cpu_post_store_table) / sizeof (struct cpu_post_store_s); + +int cpu_post_test_store (void) +{ + int ret = 0; + unsigned int i; + + for (i = 0; i < cpu_post_store_size && ret == 0; i++) + { + struct cpu_post_store_s *test = cpu_post_store_table + i; + uchar data[16] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; + ulong base0 = (ulong) (data + 8); + ulong base = base0; + + if (test->index) + { + ulong code[] = + { + ASM_12(test->cmd, 5, 3, 4), + ASM_BLR, + }; + + cpu_post_exec_12w (code, &base, test->offset, test->value); + } + else + { + ulong code[] = + { + ASM_11I(test->cmd, 4, 3, test->offset), + ASM_BLR, + }; + + cpu_post_exec_11w (code, &base, test->value); + } + + if (ret == 0) + { + if (test->update) + ret = base == base0 + test->offset ? 0 : -1; + else + ret = base == base0 ? 0 : -1; + } + + if (ret == 0) + { + switch (test->width) + { + case 1: + ret = *(uchar *)(base0 + test->offset) == test->value ? + 0 : -1; + break; + case 2: + ret = *(ushort *)(base0 + test->offset) == test->value ? + 0 : -1; + break; + case 4: + ret = *(ulong *)(base0 + test->offset) == test->value ? + 0 : -1; + break; + } + } + + if (ret != 0) + { + post_log ("Error at store test %d !\n", i); + } + } + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/string.c b/post/lib_ppc/string.c new file mode 100644 index 00000000000..bd83bd13628 --- /dev/null +++ b/post/lib_ppc/string.c @@ -0,0 +1,106 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Load/store string instructions: lswi, stswi, lswx, stswx + * + * Several consecutive bytes from a source memory buffer are loaded + * left to right into GPRs. After that, the bytes are stored + * from the GPRs into a target memory buffer. The contents + * of the source and target buffers are then compared. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2); +extern void cpu_post_exec_04 (ulong *code, ulong op1, ulong op2, ulong op3, + ulong op4); + +#include +int cpu_post_test_string (void) +{ + int ret = 0; + unsigned int i; + + if (ret == 0) + { + char src [31], dst [31]; + + ulong code[] = + { + ASM_LSWI(5, 3, 31), + ASM_STSWI(5, 4, 31), + ASM_BLR, + }; + + for (i = 0; i < sizeof(src); i ++) + { + src[i] = (char) i; + dst[i] = 0; + } + + cpu_post_exec_02(code, (ulong)src, (ulong)dst); + + ret = memcmp(src, dst, sizeof(dst)) == 0 ? 0 : -1; + } + + if (ret == 0) + { + char src [95], dst [95]; + + ulong code[] = + { + ASM_LSWX(8, 3, 5), + ASM_STSWX(8, 4, 5), + ASM_BLR, + }; + + for (i = 0; i < sizeof(src); i ++) + { + src[i] = (char) i; + dst[i] = 0; + } + + cpu_post_exec_04(code, (ulong)src, (ulong)dst, 0, sizeof(src)); + + ret = memcmp(src, dst, sizeof(dst)) == 0 ? 0 : -1; + } + + if (ret != 0) + { + post_log ("Error at string test !\n"); + } + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/three.c b/post/lib_ppc/three.c new file mode 100644 index 00000000000..c2d7476047f --- /dev/null +++ b/post/lib_ppc/three.c @@ -0,0 +1,259 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Ternary instructions instr rD,rA,rB + * + * Arithmetic instructions: add, addc, adde, subf, subfc, subfe, + * mullw, mulhw, mulhwu, divw, divwu + * + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1, + ulong op2); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_three_s +{ + ulong cmd; + ulong op1; + ulong op2; + ulong res; +} cpu_post_three_table[] = +{ + { + OP_ADD, + 100, + 200, + 300 + }, + { + OP_ADD, + 100, + -200, + -100 + }, + { + OP_ADDC, + 100, + 200, + 300 + }, + { + OP_ADDC, + 100, + -200, + -100 + }, + { + OP_ADDE, + 100, + 200, + 300 + }, + { + OP_ADDE, + 100, + -200, + -100 + }, + { + OP_SUBF, + 100, + 200, + 100 + }, + { + OP_SUBF, + 300, + 200, + -100 + }, + { + OP_SUBFC, + 100, + 200, + 100 + }, + { + OP_SUBFC, + 300, + 200, + -100 + }, + { + OP_SUBFE, + 100, + 200, + 200 + ~100 + }, + { + OP_SUBFE, + 300, + 200, + 200 + ~300 + }, + { + OP_MULLW, + 200, + 300, + 200 * 300 + }, + { + OP_MULHW, + 0x10000000, + 0x10000000, + 0x1000000 + }, + { + OP_MULHWU, + 0x80000000, + 0x80000000, + 0x40000000 + }, + { + OP_DIVW, + -20, + 5, + -4 + }, + { + OP_DIVWU, + 0x8000, + 0x200, + 0x40 + }, +}; +static unsigned int cpu_post_three_size = + sizeof (cpu_post_three_table) / sizeof (struct cpu_post_three_s); + +int cpu_post_test_three (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_three_size && ret == 0; i++) + { + struct cpu_post_three_s *test = cpu_post_three_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int reg2 = (reg + 2) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -24), + ASM_STW(3, stk, 12), + ASM_STW(4, stk, 16), + ASM_STW(reg0, stk, 8), + ASM_STW(reg1, stk, 4), + ASM_STW(reg2, stk, 0), + ASM_LWZ(reg1, stk, 12), + ASM_LWZ(reg0, stk, 16), + ASM_12(test->cmd, reg2, reg1, reg0), + ASM_STW(reg2, stk, 12), + ASM_LWZ(reg2, stk, 0), + ASM_LWZ(reg1, stk, 4), + ASM_LWZ(reg0, stk, 8), + ASM_LWZ(3, stk, 12), + ASM_ADDI(1, stk, 24), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + unsigned long codecr[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -24), + ASM_STW(3, stk, 12), + ASM_STW(4, stk, 16), + ASM_STW(reg0, stk, 8), + ASM_STW(reg1, stk, 4), + ASM_STW(reg2, stk, 0), + ASM_LWZ(reg1, stk, 12), + ASM_LWZ(reg0, stk, 16), + ASM_12(test->cmd, reg2, reg1, reg0) | BIT_C, + ASM_STW(reg2, stk, 12), + ASM_LWZ(reg2, stk, 0), + ASM_LWZ(reg1, stk, 4), + ASM_LWZ(reg0, stk, 8), + ASM_LWZ(3, stk, 12), + ASM_ADDI(1, stk, 24), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + if (ret == 0) + { + cr = 0; + cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at three test %d !\n", i); + } + } + + if (ret == 0) + { + cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2); + + ret = res == test->res && + (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at three test %d !\n", i); + } + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/threei.c b/post/lib_ppc/threei.c new file mode 100644 index 00000000000..79f01789c00 --- /dev/null +++ b/post/lib_ppc/threei.c @@ -0,0 +1,137 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Ternary instructions instr rA,rS,UIMM + * + * Logic instructions: ori, oris, xori, xoris + * + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_threei_s +{ + ulong cmd; + ulong op1; + ushort op2; + ulong res; +} cpu_post_threei_table[] = +{ + { + OP_ORI, + 0x80000000, + 0xffff, + 0x8000ffff + }, + { + OP_ORIS, + 0x00008000, + 0xffff, + 0xffff8000 + }, + { + OP_XORI, + 0x8000ffff, + 0xffff, + 0x80000000 + }, + { + OP_XORIS, + 0x00008000, + 0xffff, + 0xffff8000 + }, +}; +static unsigned int cpu_post_threei_size = + sizeof (cpu_post_threei_table) / sizeof (struct cpu_post_threei_s); + +int cpu_post_test_threei (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_threei_size && ret == 0; i++) + { + struct cpu_post_threei_s *test = cpu_post_threei_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_11IX(test->cmd, reg1, reg0, test->op2), + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + cr = 0; + cpu_post_exec_21 (code, & cr, & res, test->op1); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at threei test %d !\n", i); + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/threex.c b/post/lib_ppc/threex.c new file mode 100644 index 00000000000..2c72063848e --- /dev/null +++ b/post/lib_ppc/threex.c @@ -0,0 +1,229 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Ternary instructions instr rA,rS,rB + * + * Logic instructions: or, orc, xor, nand, nor, eqv + * Shift instructions: slw, srw, sraw + * + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_22 (ulong *code, ulong *cr, ulong *res, ulong op1, + ulong op2); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_threex_s +{ + ulong cmd; + ulong op1; + ulong op2; + ulong res; +} cpu_post_threex_table[] = +{ + { + OP_OR, + 0x1234, + 0x5678, + 0x1234 | 0x5678 + }, + { + OP_ORC, + 0x1234, + 0x5678, + 0x1234 | ~0x5678 + }, + { + OP_XOR, + 0x1234, + 0x5678, + 0x1234 ^ 0x5678 + }, + { + OP_NAND, + 0x1234, + 0x5678, + ~(0x1234 & 0x5678) + }, + { + OP_NOR, + 0x1234, + 0x5678, + ~(0x1234 | 0x5678) + }, + { + OP_EQV, + 0x1234, + 0x5678, + ~(0x1234 ^ 0x5678) + }, + { + OP_SLW, + 0x80, + 16, + 0x800000 + }, + { + OP_SLW, + 0x80, + 32, + 0 + }, + { + OP_SRW, + 0x800000, + 16, + 0x80 + }, + { + OP_SRW, + 0x800000, + 32, + 0 + }, + { + OP_SRAW, + 0x80000000, + 3, + 0xf0000000 + }, + { + OP_SRAW, + 0x8000, + 3, + 0x1000 + }, +}; +static unsigned int cpu_post_threex_size = + sizeof (cpu_post_threex_table) / sizeof (struct cpu_post_threex_s); + +int cpu_post_test_threex (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_threex_size && ret == 0; i++) + { + struct cpu_post_threex_s *test = cpu_post_threex_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int reg2 = (reg + 2) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -24), + ASM_STW(3, stk, 12), + ASM_STW(4, stk, 16), + ASM_STW(reg0, stk, 8), + ASM_STW(reg1, stk, 4), + ASM_STW(reg2, stk, 0), + ASM_LWZ(reg1, stk, 12), + ASM_LWZ(reg0, stk, 16), + ASM_12X(test->cmd, reg2, reg1, reg0), + ASM_STW(reg2, stk, 12), + ASM_LWZ(reg2, stk, 0), + ASM_LWZ(reg1, stk, 4), + ASM_LWZ(reg0, stk, 8), + ASM_LWZ(3, stk, 12), + ASM_ADDI(1, stk, 24), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + unsigned long codecr[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -24), + ASM_STW(3, stk, 12), + ASM_STW(4, stk, 16), + ASM_STW(reg0, stk, 8), + ASM_STW(reg1, stk, 4), + ASM_STW(reg2, stk, 0), + ASM_LWZ(reg1, stk, 12), + ASM_LWZ(reg0, stk, 16), + ASM_12X(test->cmd, reg2, reg1, reg0) | BIT_C, + ASM_STW(reg2, stk, 12), + ASM_LWZ(reg2, stk, 0), + ASM_LWZ(reg1, stk, 4), + ASM_LWZ(reg0, stk, 8), + ASM_LWZ(3, stk, 12), + ASM_ADDI(1, stk, 24), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + if (ret == 0) + { + cr = 0; + cpu_post_exec_22 (code, & cr, & res, test->op1, test->op2); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at threex test %d !\n", i); + } + } + + if (ret == 0) + { + cpu_post_exec_22 (codecr, & cr, & res, test->op1, test->op2); + + ret = res == test->res && + (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at threex test %d !\n", i); + } + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/two.c b/post/lib_ppc/two.c new file mode 100644 index 00000000000..cfbac5e6208 --- /dev/null +++ b/post/lib_ppc/two.c @@ -0,0 +1,176 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Binary instructions instr rD,rA + * + * Logic instructions: neg + * Arithmetic instructions: addme, addze, subfme, subfze + + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_two_s +{ + ulong cmd; + ulong op; + ulong res; +} cpu_post_two_table[] = +{ + { + OP_NEG, + 3, + -3 + }, + { + OP_NEG, + 5, + -5 + }, + { + OP_ADDME, + 6, + 5 + }, + { + OP_ADDZE, + 5, + 5 + }, + { + OP_SUBFME, + 6, + ~6 - 1 + }, + { + OP_SUBFZE, + 5, + ~5 + }, +}; +static unsigned int cpu_post_two_size = + sizeof (cpu_post_two_table) / sizeof (struct cpu_post_two_s); + +int cpu_post_test_two (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_two_size && ret == 0; i++) + { + struct cpu_post_two_s *test = cpu_post_two_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_11(test->cmd, reg1, reg0), + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + unsigned long codecr[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_11(test->cmd, reg1, reg0) | BIT_C, + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + if (ret == 0) + { + cr = 0; + cpu_post_exec_21 (code, & cr, & res, test->op); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at two test %d !\n", i); + } + } + + if (ret == 0) + { + cpu_post_exec_21 (codecr, & cr, & res, test->op); + + ret = res == test->res && + (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at two test %d !\n", i); + } + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif diff --git a/post/lib_ppc/twox.c b/post/lib_ppc/twox.c new file mode 100644 index 00000000000..48d9954ca48 --- /dev/null +++ b/post/lib_ppc/twox.c @@ -0,0 +1,176 @@ +/* + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include + +/* + * CPU test + * Binary instructions instr rA,rS + * + * Logic instructions: cntlzw + * Arithmetic instructions: extsb, extsh + + * The test contains a pre-built table of instructions, operands and + * expected results. For each table entry, the test will cyclically use + * different sets of operand registers and result registers. + */ + +#ifdef CONFIG_POST + +#include +#include "cpu_asm.h" + +#if CONFIG_POST & CFG_POST_CPU + +extern void cpu_post_exec_21 (ulong *code, ulong *cr, ulong *res, ulong op1); +extern ulong cpu_post_makecr (long v); + +static struct cpu_post_twox_s +{ + ulong cmd; + ulong op; + ulong res; +} cpu_post_twox_table[] = +{ + { + OP_EXTSB, + 3, + 3 + }, + { + OP_EXTSB, + 0xff, + -1 + }, + { + OP_EXTSH, + 3, + 3 + }, + { + OP_EXTSH, + 0xff, + 0xff + }, + { + OP_EXTSH, + 0xffff, + -1 + }, + { + OP_CNTLZW, + 0x000fffff, + 12 + }, +}; +static unsigned int cpu_post_twox_size = + sizeof (cpu_post_twox_table) / sizeof (struct cpu_post_twox_s); + +int cpu_post_test_twox (void) +{ + int ret = 0; + unsigned int i, reg; + int flag = disable_interrupts(); + + for (i = 0; i < cpu_post_twox_size && ret == 0; i++) + { + struct cpu_post_twox_s *test = cpu_post_twox_table + i; + + for (reg = 0; reg < 32 && ret == 0; reg++) + { + unsigned int reg0 = (reg + 0) % 32; + unsigned int reg1 = (reg + 1) % 32; + unsigned int stk = reg < 16 ? 31 : 15; + unsigned long code[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_11X(test->cmd, reg1, reg0), + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + unsigned long codecr[] = + { + ASM_STW(stk, 1, -4), + ASM_ADDI(stk, 1, -16), + ASM_STW(3, stk, 8), + ASM_STW(reg0, stk, 4), + ASM_STW(reg1, stk, 0), + ASM_LWZ(reg0, stk, 8), + ASM_11X(test->cmd, reg1, reg0) | BIT_C, + ASM_STW(reg1, stk, 8), + ASM_LWZ(reg1, stk, 0), + ASM_LWZ(reg0, stk, 4), + ASM_LWZ(3, stk, 8), + ASM_ADDI(1, stk, 16), + ASM_LWZ(stk, 1, -4), + ASM_BLR, + }; + ulong res; + ulong cr; + + if (ret == 0) + { + cr = 0; + cpu_post_exec_21 (code, & cr, & res, test->op); + + ret = res == test->res && cr == 0 ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at twox test %d !\n", i); + } + } + + if (ret == 0) + { + cpu_post_exec_21 (codecr, & cr, & res, test->op); + + ret = res == test->res && + (cr & 0xe0000000) == cpu_post_makecr (res) ? 0 : -1; + + if (ret != 0) + { + post_log ("Error at twox test %d !\n", i); + } + } + } + } + + if (flag) + enable_interrupts(); + + return ret; +} + +#endif +#endif -- cgit v1.2.3