Restructure POST directory to support of other CPUs, boards, etc.
diff --git a/post/lib_ppc/Makefile b/post/lib_ppc/Makefile
new file mode 100644
index 0000000..14354a0
--- /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 0000000..7ddf2ab
--- /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 0000000..a0815a4
--- /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 0000000..b4b17c8
--- /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 0000000..789a24c
--- /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 0000000..e0c2aaf
--- /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 0000000..033584b
--- /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 0000000..1f2ded2
--- /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 0000000..1cbaf41
--- /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 0000000..da6ef37
--- /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 0000000..393c568
--- /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 0000000..8724384
--- /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 0000000..f65f79a
--- /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 0000000..e240c41
--- /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 0000000..523cf4d
--- /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 0000000..91c82c9
--- /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 0000000..f495bf2
--- /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 0000000..bd83bd1
--- /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 0000000..c2d7476
--- /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 0000000..79f0178
--- /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 0000000..2c72063
--- /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 0000000..cfbac5e
--- /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 0000000..48d9954
--- /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