Initial revision
diff --git a/post/cpu/andi.c b/post/cpu/andi.c
new file mode 100644
index 0000000..7ddf2ab
--- /dev/null
+++ b/post/cpu/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/cpu/asm.S b/post/cpu/asm.S
new file mode 100644
index 0000000..a0815a4
--- /dev/null
+++ b/post/cpu/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/cpu/complex.c b/post/cpu/complex.c
new file mode 100644
index 0000000..dc8b080
--- /dev/null
+++ b/post/cpu/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/cpu/load.c b/post/cpu/load.c
new file mode 100644
index 0000000..b3418ef
--- /dev/null
+++ b/post/cpu/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/cpu/multi.c b/post/cpu/multi.c
new file mode 100644
index 0000000..bdad5d9
--- /dev/null
+++ b/post/cpu/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/cpu/rlwimi.c b/post/cpu/rlwimi.c
new file mode 100644
index 0000000..f65f79a
--- /dev/null
+++ b/post/cpu/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/cpu/rlwinm.c b/post/cpu/rlwinm.c
new file mode 100644
index 0000000..e240c41
--- /dev/null
+++ b/post/cpu/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/cpu/rlwnm.c b/post/cpu/rlwnm.c
new file mode 100644
index 0000000..523cf4d
--- /dev/null
+++ b/post/cpu/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/cpu/srawi.c b/post/cpu/srawi.c
new file mode 100644
index 0000000..91c82c9
--- /dev/null
+++ b/post/cpu/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/cpu/store.c b/post/cpu/store.c
new file mode 100644
index 0000000..e5189c7
--- /dev/null
+++ b/post/cpu/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/cpu/string.c b/post/cpu/string.c
new file mode 100644
index 0000000..a19a755
--- /dev/null
+++ b/post/cpu/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