diff options
Diffstat (limited to 'post/lib_ppc')
| -rw-r--r-- | post/lib_ppc/Makefile | 32 | ||||
| -rw-r--r-- | post/lib_ppc/andi.c | 123 | ||||
| -rw-r--r-- | post/lib_ppc/asm.S | 346 | ||||
| -rw-r--r-- | post/lib_ppc/b.c | 197 | ||||
| -rw-r--r-- | post/lib_ppc/cmp.c | 133 | ||||
| -rw-r--r-- | post/lib_ppc/cmpi.c | 133 | ||||
| -rw-r--r-- | post/lib_ppc/complex.c | 126 | ||||
| -rw-r--r-- | post/lib_ppc/cpu.c | 139 | ||||
| -rw-r--r-- | post/lib_ppc/cpu_asm.h | 224 | ||||
| -rw-r--r-- | post/lib_ppc/cr.c | 356 | ||||
| -rw-r--r-- | post/lib_ppc/load.c | 255 | ||||
| -rw-r--r-- | post/lib_ppc/multi.c | 81 | ||||
| -rw-r--r-- | post/lib_ppc/rlwimi.c | 162 | ||||
| -rw-r--r-- | post/lib_ppc/rlwinm.c | 155 | ||||
| -rw-r--r-- | post/lib_ppc/rlwnm.c | 165 | ||||
| -rw-r--r-- | post/lib_ppc/srawi.c | 156 | ||||
| -rw-r--r-- | post/lib_ppc/store.c | 235 | ||||
| -rw-r--r-- | post/lib_ppc/string.c | 106 | ||||
| -rw-r--r-- | post/lib_ppc/three.c | 259 | ||||
| -rw-r--r-- | post/lib_ppc/threei.c | 137 | ||||
| -rw-r--r-- | post/lib_ppc/threex.c | 229 | ||||
| -rw-r--r-- | post/lib_ppc/two.c | 176 | ||||
| -rw-r--r-- | post/lib_ppc/twox.c | 176 | 
23 files changed, 4101 insertions, 0 deletions
| diff --git a/post/lib_ppc/Makefile b/post/lib_ppc/Makefile new file mode 100644 index 000000000..14354a032 --- /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 000000000..7ddf2ab2f --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..a0815a43a --- /dev/null +++ b/post/lib_ppc/asm.S @@ -0,0 +1,346 @@ +/* + *  Copyright (C) 2002 Wolfgang Denk <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 <config.h> + +#ifdef CONFIG_POST + +#include <post.h> +#include <ppc_asm.tmpl> +#include <ppc_defs.h> +#include <asm/cache.h> + +#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 000000000..b4b17c8ff --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..789a24cb7 --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..e0c2aaff8 --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..033584bec --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..1f2ded2bf --- /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 <common.h> + +/* + * 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 <watchdog.h> +#include <post.h> + +#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 000000000..1cbaf4121 --- /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 000000000..da6ef3745 --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..393c56830 --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..872438478 --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..f65f79a8e --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..e240c41b1 --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..523cf4da5 --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..91c82c915 --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..f495bf2aa --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..bd83bd136 --- /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 <common.h> + +/* + * 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 <post.h> +#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 <bedbug/regs.h> +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 000000000..c2d747604 --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..79f01789c --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..2c7206384 --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..cfbac5e62 --- /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 <common.h> + +/* + * 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 <post.h> +#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 000000000..48d9954ca --- /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 <common.h> + +/* + * 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 <post.h> +#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 |