summaryrefslogtreecommitdiffstats
path: root/post/lib_powerpc
diff options
context:
space:
mode:
authorStefan Roese <sr@denx.de>2010-04-15 16:07:28 +0200
committerWolfgang Denk <wd@denx.de>2010-04-21 23:42:38 +0200
commita47a12becf66f02a56da91c161e2edb625e9f20c (patch)
tree6efae7137d26d1e610c5fd56b7aaa3c043ad2b71 /post/lib_powerpc
parent254ab7bd464657600aba69d840406f9358f3e116 (diff)
downloadblackbird-obmc-uboot-a47a12becf66f02a56da91c161e2edb625e9f20c.tar.gz
blackbird-obmc-uboot-a47a12becf66f02a56da91c161e2edb625e9f20c.zip
Move arch/ppc to arch/powerpc
As discussed on the list, move "arch/ppc" to "arch/powerpc" to better match the Linux directory structure. Please note that this patch also changes the "ppc" target in MAKEALL to "powerpc" to match this new infrastructure. But "ppc" is kept as an alias for now, to not break compatibility with scripts using this name. Signed-off-by: Stefan Roese <sr@denx.de> Acked-by: Wolfgang Denk <wd@denx.de> Acked-by: Detlev Zundel <dzu@denx.de> Acked-by: Kim Phillips <kim.phillips@freescale.com> Cc: Peter Tyser <ptyser@xes-inc.com> Cc: Anatolij Gustschin <agust@denx.de>
Diffstat (limited to 'post/lib_powerpc')
-rw-r--r--post/lib_powerpc/Makefile32
-rw-r--r--post/lib_powerpc/andi.c120
-rw-r--r--post/lib_powerpc/asm.S358
-rw-r--r--post/lib_powerpc/b.c198
-rw-r--r--post/lib_powerpc/cmp.c134
-rw-r--r--post/lib_powerpc/cmpi.c134
-rw-r--r--post/lib_powerpc/complex.c127
-rw-r--r--post/lib_powerpc/cpu.c147
-rw-r--r--post/lib_powerpc/cpu_asm.h224
-rw-r--r--post/lib_powerpc/cr.c357
-rw-r--r--post/lib_powerpc/fpu/20001122-1.c61
-rw-r--r--post/lib_powerpc/fpu/20010114-2.c65
-rw-r--r--post/lib_powerpc/fpu/20010226-1.c53
-rw-r--r--post/lib_powerpc/fpu/980619-1.c59
-rw-r--r--post/lib_powerpc/fpu/Makefile33
-rw-r--r--post/lib_powerpc/fpu/acc1.c56
-rw-r--r--post/lib_powerpc/fpu/compare-fp-1.c224
-rw-r--r--post/lib_powerpc/fpu/fpu.c91
-rw-r--r--post/lib_powerpc/fpu/mul-subnormal-single-1.c102
-rw-r--r--post/lib_powerpc/load.c256
-rw-r--r--post/lib_powerpc/multi.c82
-rw-r--r--post/lib_powerpc/rlwimi.c159
-rw-r--r--post/lib_powerpc/rlwinm.c152
-rw-r--r--post/lib_powerpc/rlwnm.c162
-rw-r--r--post/lib_powerpc/srawi.c153
-rw-r--r--post/lib_powerpc/store.c236
-rw-r--r--post/lib_powerpc/string.c107
-rw-r--r--post/lib_powerpc/three.c256
-rw-r--r--post/lib_powerpc/threei.c134
-rw-r--r--post/lib_powerpc/threex.c226
-rw-r--r--post/lib_powerpc/two.c173
-rw-r--r--post/lib_powerpc/twox.c173
32 files changed, 4844 insertions, 0 deletions
diff --git a/post/lib_powerpc/Makefile b/post/lib_powerpc/Makefile
new file mode 100644
index 0000000000..0cd15cfa13
--- /dev/null
+++ b/post/lib_powerpc/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
+#
+include $(TOPDIR)/config.mk
+
+LIB = libpost$(ARCH).a
+
+AOBJS-$(CONFIG_HAS_POST) += asm.o
+COBJS-$(CONFIG_HAS_POST) += cpu.o cmp.o cmpi.o two.o twox.o three.o threex.o
+COBJS-$(CONFIG_HAS_POST) += threei.o andi.o srawi.o rlwnm.o rlwinm.o rlwimi.o
+COBJS-$(CONFIG_HAS_POST) += store.o load.o cr.o b.o multi.o string.o complex.o
+
+include $(TOPDIR)/post/rules.mk
diff --git a/post/lib_powerpc/andi.c b/post/lib_powerpc/andi.c
new file mode 100644
index 0000000000..52ec7c4d4e
--- /dev/null
+++ b/post/lib_powerpc/andi.c
@@ -0,0 +1,120 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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
diff --git a/post/lib_powerpc/asm.S b/post/lib_powerpc/asm.S
new file mode 100644
index 0000000000..f6b329aa4d
--- /dev/null
+++ b/post/lib_powerpc/asm.S
@@ -0,0 +1,358 @@
+/*
+ * 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>
+
+#include <post.h>
+#include <ppc_asm.tmpl>
+#include <ppc_defs.h>
+#include <asm/cache.h>
+
+#if CONFIG_POST & CONFIG_SYS_POST_CPU
+
+/* void cpu_post_exec_02 (ulong *code, ulong op1, ulong op2); */
+ .global cpu_post_exec_02
+cpu_post_exec_02:
+ isync
+ 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:
+ isync
+ 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:
+ isync
+ 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:
+ isync
+ 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:
+ isync
+ 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:
+ isync
+ 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:
+ isync
+ 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:
+ isync
+ 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:
+ isync
+ 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:
+ isync
+ 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:
+ isync
+ 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:
+ isync
+ 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
+
+ mfcr r7
+ blrl
+ mtcr r7
+
+ 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
diff --git a/post/lib_powerpc/b.c b/post/lib_powerpc/b.c
new file mode 100644
index 0000000000..492fba4c53
--- /dev/null
+++ b/post/lib_powerpc/b.c
@@ -0,0 +1,198 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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 decr, 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 (decr)
+ 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;
+ int flag = disable_interrupts();
+
+ 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 decr = 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, decr, link,
+ ctr, cr);
+
+ if (ret != 0)
+ {
+ post_log ("Error at b3 test %d !\n", i);
+ }
+
+ i++;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (flag)
+ enable_interrupts();
+
+ return ret;
+}
+
+#endif
diff --git a/post/lib_powerpc/cmp.c b/post/lib_powerpc/cmp.c
new file mode 100644
index 0000000000..5f6a3b9046
--- /dev/null
+++ b/post/lib_powerpc/cmp.c
@@ -0,0 +1,134 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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;
+ int flag = disable_interrupts();
+
+ 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);
+ }
+ }
+
+ if (flag)
+ enable_interrupts();
+
+ return ret;
+}
+
+#endif
diff --git a/post/lib_powerpc/cmpi.c b/post/lib_powerpc/cmpi.c
new file mode 100644
index 0000000000..1a2fc3d094
--- /dev/null
+++ b/post/lib_powerpc/cmpi.c
@@ -0,0 +1,134 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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;
+ int flag = disable_interrupts();
+
+ 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);
+ }
+ }
+
+ if (flag)
+ enable_interrupts();
+
+ return ret;
+}
+
+#endif
diff --git a/post/lib_powerpc/complex.c b/post/lib_powerpc/complex.c
new file mode 100644
index 0000000000..4a3bc00031
--- /dev/null
+++ b/post/lib_powerpc/complex.c
@@ -0,0 +1,127 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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;
+ int flag = disable_interrupts();
+
+ 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");
+ }
+
+ if (flag)
+ enable_interrupts();
+
+ return ret;
+}
+
+#endif
diff --git a/post/lib_powerpc/cpu.c b/post/lib_powerpc/cpu.c
new file mode 100644
index 0000000000..3793a60c3e
--- /dev/null
+++ b/post/lib_powerpc/cpu.c
@@ -0,0 +1,147 @@
+/*
+ * (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.
+ */
+
+#include <watchdog.h>
+#include <post.h>
+#include <asm/mmu.h>
+
+#if CONFIG_POST & CONFIG_SYS_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);
+
+DECLARE_GLOBAL_DATA_PTR;
+
+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 ();
+#ifdef CONFIG_4xx_DCACHE
+ /* disable cache */
+ change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, TLB_WORD2_I_ENABLE);
+#endif
+
+ 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 ();
+#ifdef CONFIG_4xx_DCACHE
+ /* enable cache */
+ change_tlb(gd->bd->bi_memstart, gd->bd->bi_memsize, 0);
+#endif
+
+ WATCHDOG_RESET();
+
+ return ret;
+}
+
+#endif /* CONFIG_POST & CONFIG_SYS_POST_CPU */
diff --git a/post/lib_powerpc/cpu_asm.h b/post/lib_powerpc/cpu_asm.h
new file mode 100644
index 0000000000..ef6fe61eff
--- /dev/null
+++ b/post/lib_powerpc/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_powerpc/cr.c b/post/lib_powerpc/cr.c
new file mode 100644
index 0000000000..fbee6d5c40
--- /dev/null
+++ b/post/lib_powerpc/cr.c
@@ -0,0 +1,357 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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;
+ int flag = disable_interrupts();
+
+ 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));
+
+ if (flag)
+ enable_interrupts();
+
+ return ret;
+}
+
+#endif
diff --git a/post/lib_powerpc/fpu/20001122-1.c b/post/lib_powerpc/fpu/20001122-1.c
new file mode 100644
index 0000000000..bef80c5f79
--- /dev/null
+++ b/post/lib_powerpc/fpu/20001122-1.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2007
+ * 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
+ */
+/*
+ * This file is originally a part of the GCC testsuite.
+ */
+
+#include <common.h>
+
+#include <post.h>
+
+#if CONFIG_POST & CONFIG_SYS_POST_FPU
+
+GNU_FPOST_ATTR
+
+int fpu_post_test_math1 (void)
+{
+ volatile double a, *p;
+ double c, d;
+ volatile double b;
+
+ d = 1.0;
+ p = &b;
+
+ do
+ {
+ c = d;
+ d = c * 0.5;
+ b = 1 + d;
+ } while (b != 1.0);
+
+ a = 1.0 + c;
+
+ if (a == 1.0) {
+ post_log ("Error in FPU math1 test\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */
diff --git a/post/lib_powerpc/fpu/20010114-2.c b/post/lib_powerpc/fpu/20010114-2.c
new file mode 100644
index 0000000000..ee564e8d62
--- /dev/null
+++ b/post/lib_powerpc/fpu/20010114-2.c
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2007
+ * 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
+ */
+/*
+ * This file is originally a part of the GCC testsuite.
+ */
+
+#include <common.h>
+
+#include <post.h>
+
+#if CONFIG_POST & CONFIG_SYS_POST_FPU
+
+GNU_FPOST_ATTR
+
+static float rintf (float x)
+{
+ volatile float TWO23 = 8388608.0;
+
+ if (__builtin_fabs (x) < TWO23)
+ {
+ if (x > 0.0)
+ {
+ x += TWO23;
+ x -= TWO23;
+ }
+ else if (x < 0.0)
+ {
+ x = TWO23 - x;
+ x = -(x - TWO23);
+ }
+ }
+
+ return x;
+}
+
+int fpu_post_test_math2 (void)
+{
+ if (rintf (-1.5) != -2.0) {
+ post_log ("Error in FPU math2 test\n");
+ return -1;
+ }
+ return 0;
+}
+
+#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */
diff --git a/post/lib_powerpc/fpu/20010226-1.c b/post/lib_powerpc/fpu/20010226-1.c
new file mode 100644
index 0000000000..099ca4a64f
--- /dev/null
+++ b/post/lib_powerpc/fpu/20010226-1.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2007
+ * 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
+ */
+/*
+ * This file is originally a part of the GCC testsuite.
+ */
+
+#include <common.h>
+
+#include <post.h>
+
+#if CONFIG_POST & CONFIG_SYS_POST_FPU
+
+GNU_FPOST_ATTR
+
+int fpu_post_test_math3 (void)
+{
+ volatile long double dfrom = 1.1;
+ volatile long double m1;
+ volatile long double m2;
+ volatile unsigned long mant_long;
+
+ m1 = dfrom / 2.0;
+ m2 = m1 * 4294967296.0;
+ mant_long = ((unsigned long) m2) & 0xffffffff;
+
+ if (mant_long != 0x8ccccccc) {
+ post_log ("Error in FPU math3 test\n");
+ return -1;
+ }
+ return 0;
+}
+
+#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */
diff --git a/post/lib_powerpc/fpu/980619-1.c b/post/lib_powerpc/fpu/980619-1.c
new file mode 100644
index 0000000000..46a31aec45
--- /dev/null
+++ b/post/lib_powerpc/fpu/980619-1.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2007
+ * 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
+ */
+/*
+ * This file is originally a part of the GCC testsuite.
+ */
+
+#include <common.h>
+
+#include <post.h>
+
+#if CONFIG_POST & CONFIG_SYS_POST_FPU
+
+GNU_FPOST_ATTR
+
+int fpu_post_test_math4 (void)
+{
+ volatile float reale = 1.0f;
+ volatile float oneplus;
+ int i;
+
+ if (sizeof (float) != 4)
+ return 0;
+
+ for (i = 0; ; i++)
+ {
+ oneplus = 1.0f + reale;
+ if (oneplus == 1.0f)
+ break;
+ reale = reale / 2.0f;
+ }
+ /* Assumes ieee754 accurate arithmetic above. */
+ if (i != 24) {
+ post_log ("Error in FPU math4 test\n");
+ return -1;
+ }
+ return 0;
+}
+
+#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */
diff --git a/post/lib_powerpc/fpu/Makefile b/post/lib_powerpc/fpu/Makefile
new file mode 100644
index 0000000000..25726db73d
--- /dev/null
+++ b/post/lib_powerpc/fpu/Makefile
@@ -0,0 +1,33 @@
+#
+# (C) Copyright 2007
+# 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 $(TOPDIR)/config.mk
+
+LIB = libpost$(ARCH)fpu.a
+
+COBJS-$(CONFIG_HAS_POST) += fpu.o 20001122-1.o 20010114-2.o 20010226-1.o 980619-1.o
+COBJS-$(CONFIG_HAS_POST) += acc1.o compare-fp-1.o mul-subnormal-single-1.o
+
+include $(TOPDIR)/post/rules.mk
+
+CFLAGS := $(shell echo $(CFLAGS) | sed s/-msoft-float//)
+CFLAGS += -mhard-float -fkeep-inline-functions
diff --git a/post/lib_powerpc/fpu/acc1.c b/post/lib_powerpc/fpu/acc1.c
new file mode 100644
index 0000000000..9fca9b3788
--- /dev/null
+++ b/post/lib_powerpc/fpu/acc1.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2007
+ * 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
+ */
+/*
+ * This file is originally a part of the GCC testsuite.
+ */
+
+#include <common.h>
+
+#include <post.h>
+
+#if CONFIG_POST & CONFIG_SYS_POST_FPU
+
+GNU_FPOST_ATTR
+
+static double func (const double *array)
+{
+ double d = *array;
+
+ if (d == 0.0)
+ return d;
+ else
+ return d + func (array + 1);
+}
+
+int fpu_post_test_math5 (void)
+{
+ double values[] = { 0.1e-100, 1.0, -1.0, 0.0 };
+
+ if (func (values) != 0.1e-100) {
+ post_log ("Error in FPU math5 test\n");
+ return -1;
+ }
+ return 0;
+}
+
+#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */
diff --git a/post/lib_powerpc/fpu/compare-fp-1.c b/post/lib_powerpc/fpu/compare-fp-1.c
new file mode 100644
index 0000000000..f836b29c08
--- /dev/null
+++ b/post/lib_powerpc/fpu/compare-fp-1.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (C) 2007
+ * 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
+ */
+/*
+ * Test for correctness of composite floating-point comparisons.
+ * Written by Paolo Bonzini, 26th May 2004.
+ * This file is originally a part of the GCC testsuite.
+ */
+
+#include <common.h>
+
+#include <post.h>
+
+#if CONFIG_POST & CONFIG_SYS_POST_FPU
+
+GNU_FPOST_ATTR
+
+static int failed;
+
+#define TEST(c) if ((c) != ok) failed++
+#define ORD(a, b) (!__builtin_isunordered ((a), (b)))
+#define UNORD(a, b) (__builtin_isunordered ((a), (b)))
+#define UNEQ(a, b) (__builtin_isunordered ((a), (b)) || ((a) == (b)))
+#define UNLT(a, b) (__builtin_isunordered ((a), (b)) || ((a) < (b)))
+#define UNLE(a, b) (__builtin_isunordered ((a), (b)) || ((a) <= (b)))
+#define UNGT(a, b) (__builtin_isunordered ((a), (b)) || ((a) > (b)))
+#define UNGE(a, b) (__builtin_isunordered ((a), (b)) || ((a) >= (b)))
+#define LTGT(a, b) (__builtin_islessgreater ((a), (b)))
+
+static float pinf;
+static float ninf;
+static float NaN;
+
+static void iuneq (float x, float y, int ok)
+{
+ TEST (UNEQ (x, y));
+ TEST (!LTGT (x, y));
+ TEST (UNLE (x, y) && UNGE (x,y));
+}
+
+static void ieq (float x, float y, int ok)
+{
+ TEST (ORD (x, y) && UNEQ (x, y));
+}
+
+static void iltgt (float x, float y, int ok)
+{
+ TEST (!UNEQ (x, y)); /* Not optimizable. */
+ TEST (LTGT (x, y)); /* Same, __builtin_islessgreater does not trap. */
+ TEST (ORD (x, y) && (UNLT (x, y) || UNGT (x,y)));
+}
+
+static void ine (float x, float y, int ok)
+{
+ TEST (UNLT (x, y) || UNGT (x, y));
+}
+
+static void iunlt (float x, float y, int ok)
+{
+ TEST (UNLT (x, y));
+ TEST (UNORD (x, y) || (x < y));
+}
+
+static void ilt (float x, float y, int ok)
+{
+ TEST (ORD (x, y) && UNLT (x, y)); /* Not optimized */
+ TEST ((x <= y) && (x != y));
+ TEST ((x <= y) && (y != x));
+ TEST ((x != y) && (x <= y)); /* Not optimized */
+ TEST ((y != x) && (x <= y)); /* Not optimized */
+}
+
+static void iunle (float x, float y, int ok)
+{
+ TEST (UNLE (x, y));
+ TEST (UNORD (x, y) || (x <= y));
+}
+
+static void ile (float x, float y, int ok)
+{
+ TEST (ORD (x, y) && UNLE (x, y)); /* Not optimized */
+ TEST ((x < y) || (x == y));
+ TEST ((y > x) || (x == y));
+ TEST ((x == y) || (x < y)); /* Not optimized */
+ TEST ((y == x) || (x < y)); /* Not optimized */
+}
+
+static void iungt (float x, float y, int ok)
+{
+ TEST (UNGT (x, y));
+ TEST (UNORD (x, y) || (x > y));
+}
+
+static void igt (float x, float y, int ok)
+{
+ TEST (ORD (x, y) && UNGT (x, y)); /* Not optimized */
+ TEST ((x >= y) && (x != y));
+ TEST ((x >= y) && (y != x));
+ TEST ((x != y) && (x >= y)); /* Not optimized */
+ TEST ((y != x) && (x >= y)); /* Not optimized */
+}
+
+static void iunge (float x, float y, int ok)
+{
+ TEST (UNGE (x, y));
+ TEST (UNORD (x, y) || (x >= y));
+}
+
+static void ige (float x, float y, int ok)
+{
+ TEST (ORD (x, y) && UNGE (x, y)); /* Not optimized */
+ TEST ((x > y) || (x == y));
+ TEST ((y < x) || (x == y));
+ TEST ((x == y) || (x > y)); /* Not optimized */
+ TEST ((y == x) || (x > y)); /* Not optimized */
+}
+
+int fpu_post_test_math6 (void)
+{
+ pinf = __builtin_inf ();
+ ninf = -__builtin_inf ();
+ NaN = __builtin_nan ("");
+
+ iuneq (ninf, pinf, 0);
+ iuneq (NaN, NaN, 1);
+ iuneq (pinf, ninf, 0);
+ iuneq (1, 4, 0);
+ iuneq (3, 3, 1);
+ iuneq (5, 2, 0);
+
+ ieq (1, 4, 0);
+ ieq (3, 3, 1);
+ ieq (5, 2, 0);
+
+ iltgt (ninf, pinf, 1);
+ iltgt (NaN, NaN, 0);
+ iltgt (pinf, ninf, 1);
+ iltgt (1, 4, 1);
+ iltgt (3, 3, 0);
+ iltgt (5, 2, 1);
+
+ ine (1, 4, 1);
+ ine (3, 3, 0);
+ ine (5, 2, 1);
+
+ iunlt (NaN, ninf, 1);
+ iunlt (pinf, NaN, 1);
+ iunlt (pinf, ninf, 0);
+ iunlt (pinf, pinf, 0);
+ iunlt (ninf, ninf, 0);
+ iunlt (1, 4, 1);
+ iunlt (3, 3, 0);
+ iunlt (5, 2, 0);
+
+ ilt (1, 4, 1);
+ ilt (3, 3, 0);
+ ilt (5, 2, 0);
+
+ iunle (NaN, ninf, 1);
+ iunle (pinf, NaN, 1);
+ iunle (pinf, ninf, 0);
+ iunle (pinf, pinf, 1);
+ iunle (ninf, ninf, 1);
+ iunle (1, 4, 1);
+ iunle (3, 3, 1);
+ iunle (5, 2, 0);
+
+ ile (1, 4, 1);
+ ile (3, 3, 1);
+ ile (5, 2, 0);
+
+ iungt (NaN, ninf, 1);
+ iungt (pinf, NaN, 1);
+ iungt (pinf, ninf, 1);
+ iungt (pinf, pinf, 0);
+ iungt (ninf, ninf, 0);
+ iungt (1, 4, 0);
+ iungt (3, 3, 0);
+ iungt (5, 2, 1);
+
+ igt (1, 4, 0);
+ igt (3, 3, 0);
+ igt (5, 2, 1);
+
+ iunge (NaN, ninf, 1);
+ iunge (pinf, NaN, 1);
+ iunge (ninf, pinf, 0);
+ iunge (pinf, pinf, 1);
+ iunge (ninf, ninf, 1);
+ iunge (1, 4, 0);
+ iunge (3, 3, 1);
+ iunge (5, 2, 1);
+
+ ige (1, 4, 0);
+ ige (3, 3, 1);
+ ige (5, 2, 1);
+
+ if (failed) {
+ post_log ("Error in FPU math6 test\n");
+ return -1;
+ }
+ return 0;
+}
+
+#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */
diff --git a/post/lib_powerpc/fpu/fpu.c b/post/lib_powerpc/fpu/fpu.c
new file mode 100644
index 0000000000..3f3adea197
--- /dev/null
+++ b/post/lib_powerpc/fpu/fpu.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2007
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * Author: Sergei Poselenov <sposelenov@emcraft.com>
+ *
+ * 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>
+
+/*
+ * FPU 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.
+ */
+
+#include <post.h>
+
+#if CONFIG_POST & CONFIG_SYS_POST_FPU
+
+#include <watchdog.h>
+
+GNU_FPOST_ATTR
+
+extern int fpu_status (void);
+extern void fpu_enable (void);
+extern void fpu_disable (void);
+
+extern int fpu_post_test_math1 (void);
+extern int fpu_post_test_math2 (void);
+extern int fpu_post_test_math3 (void);
+extern int fpu_post_test_math4 (void);
+extern int fpu_post_test_math5 (void);
+extern int fpu_post_test_math6 (void);
+extern int fpu_post_test_math7 (void);
+
+int fpu_post_test (int flags)
+{
+ int fpu = fpu_status ();
+
+ int ret = 0;
+
+ WATCHDOG_RESET ();
+
+ if (!fpu)
+ fpu_enable ();
+
+ if (ret == 0)
+ ret = fpu_post_test_math1 ();
+ if (ret == 0)
+ ret = fpu_post_test_math2 ();
+ if (ret == 0)
+ ret = fpu_post_test_math3 ();
+ if (ret == 0)
+ ret = fpu_post_test_math4 ();
+ if (ret == 0)
+ ret = fpu_post_test_math5 ();
+ if (ret == 0)
+ ret = fpu_post_test_math6 ();
+ if (ret == 0)
+ ret = fpu_post_test_math7 ();
+
+ if (!fpu)
+ fpu_disable ();
+
+ WATCHDOG_RESET ();
+
+ return ret;
+}
+
+#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */
diff --git a/post/lib_powerpc/fpu/mul-subnormal-single-1.c b/post/lib_powerpc/fpu/mul-subnormal-single-1.c
new file mode 100644
index 0000000000..1f3732d924
--- /dev/null
+++ b/post/lib_powerpc/fpu/mul-subnormal-single-1.c
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2007
+ * 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
+ */
+/*
+ * This file is originally a part of the GCC testsuite.
+ * Check that certain subnormal numbers (formerly known as denormalized
+ * numbers) are rounded to within 0.5 ulp. PR other/14354.
+ */
+
+#include <common.h>
+
+#include <post.h>
+
+#if CONFIG_POST & CONFIG_SYS_POST_FPU
+
+GNU_FPOST_ATTR
+
+union uf
+{
+ unsigned int u;
+ float f;
+};
+
+static float
+u2f (unsigned int v)
+{
+ union uf u;
+ u.u = v;
+ return u.f;
+}
+
+static unsigned int
+f2u (float v)
+{
+ union uf u;
+ u.f = v;
+ return u.u;
+}
+
+static int ok = 1;
+
+static void
+tstmul (unsigned int ux, unsigned int uy, unsigned int ur)
+{
+ float x = u2f (ux);
+ float y = u2f (uy);
+
+ if (f2u (x * y) != ur)
+ /* Set a variable rather than aborting here, to simplify tracing when
+ several computations are wrong. */
+ ok = 0;
+}
+
+/* We don't want to make this const and static, or else we risk inlining
+ causing the test to fold as constants at compile-time. */
+struct
+{
+ unsigned int p1, p2, res;
+} static volatile expected[] =
+{
+ {0xfff, 0x3f800400, 0xfff},
+ {0xf, 0x3fc88888, 0x17},
+ {0xf, 0x3f844444, 0xf}
+};
+
+int fpu_post_test_math7 (void)
+{
+ unsigned int i;
+
+ for (i = 0; i < sizeof (expected) / sizeof (expected[0]); i++)
+ {
+ tstmul (expected[i].p1, expected[i].p2, expected[i].res);
+ tstmul (expected[i].p2, expected[i].p1, expected[i].res);
+ }
+
+ if (!ok) {
+ post_log ("Error in FPU math7 test\n");
+ return -1;
+ }
+ return 0;
+}
+
+#endif /* CONFIG_POST & CONFIG_SYS_POST_FPU */
diff --git a/post/lib_powerpc/load.c b/post/lib_powerpc/load.c
new file mode 100644
index 0000000000..98d437318c
--- /dev/null
+++ b/post/lib_powerpc/load.c
@@ -0,0 +1,256 @@
+/*
+ * (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).
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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;
+ int flag = disable_interrupts();
+
+ 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);
+ }
+ }
+
+ if (flag)
+ enable_interrupts();
+
+ return ret;
+}
+
+#endif
diff --git a/post/lib_powerpc/multi.c b/post/lib_powerpc/multi.c
new file mode 100644
index 0000000000..e42a7c07eb
--- /dev/null
+++ b/post/lib_powerpc/multi.c
@@ -0,0 +1,82 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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;
+ int flag = disable_interrupts();
+
+ 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");
+ }
+
+ if (flag)
+ enable_interrupts();
+
+ return ret;
+}
+
+#endif
diff --git a/post/lib_powerpc/rlwimi.c b/post/lib_powerpc/rlwimi.c
new file mode 100644
index 0000000000..fd628b31f9
--- /dev/null
+++ b/post/lib_powerpc/rlwimi.c
@@ -0,0 +1,159 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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
diff --git a/post/lib_powerpc/rlwinm.c b/post/lib_powerpc/rlwinm.c
new file mode 100644
index 0000000000..88a28c6431
--- /dev/null
+++ b/post/lib_powerpc/rlwinm.c
@@ -0,0 +1,152 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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
diff --git a/post/lib_powerpc/rlwnm.c b/post/lib_powerpc/rlwnm.c
new file mode 100644
index 0000000000..60bcb6d26c
--- /dev/null
+++ b/post/lib_powerpc/rlwnm.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: 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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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
diff --git a/post/lib_powerpc/srawi.c b/post/lib_powerpc/srawi.c
new file mode 100644
index 0000000000..be153aded2
--- /dev/null
+++ b/post/lib_powerpc/srawi.c
@@ -0,0 +1,153 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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
diff --git a/post/lib_powerpc/store.c b/post/lib_powerpc/store.c
new file mode 100644
index 0000000000..1956f6baa3
--- /dev/null
+++ b/post/lib_powerpc/store.c
@@ -0,0 +1,236 @@
+/*
+ * (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).
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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;
+ int flag = disable_interrupts();
+
+ 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);
+ }
+ }
+
+ if (flag)
+ enable_interrupts();
+
+ return ret;
+}
+
+#endif
diff --git a/post/lib_powerpc/string.c b/post/lib_powerpc/string.c
new file mode 100644
index 0000000000..c0ddeaf655
--- /dev/null
+++ b/post/lib_powerpc/string.c
@@ -0,0 +1,107 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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;
+ int flag = disable_interrupts();
+
+ 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");
+ }
+
+ if (flag)
+ enable_interrupts();
+
+ return ret;
+}
+
+#endif
diff --git a/post/lib_powerpc/three.c b/post/lib_powerpc/three.c
new file mode 100644
index 0000000000..7f8c1e2b86
--- /dev/null
+++ b/post/lib_powerpc/three.c
@@ -0,0 +1,256 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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
diff --git a/post/lib_powerpc/threei.c b/post/lib_powerpc/threei.c
new file mode 100644
index 0000000000..31953f9354
--- /dev/null
+++ b/post/lib_powerpc/threei.c
@@ -0,0 +1,134 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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
diff --git a/post/lib_powerpc/threex.c b/post/lib_powerpc/threex.c
new file mode 100644
index 0000000000..350a12ae78
--- /dev/null
+++ b/post/lib_powerpc/threex.c
@@ -0,0 +1,226 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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
diff --git a/post/lib_powerpc/two.c b/post/lib_powerpc/two.c
new file mode 100644
index 0000000000..2b111472b6
--- /dev/null
+++ b/post/lib_powerpc/two.c
@@ -0,0 +1,173 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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
diff --git a/post/lib_powerpc/twox.c b/post/lib_powerpc/twox.c
new file mode 100644
index 0000000000..d6714f9861
--- /dev/null
+++ b/post/lib_powerpc/twox.c
@@ -0,0 +1,173 @@
+/*
+ * (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.
+ */
+
+#include <post.h>
+#include "cpu_asm.h"
+
+#if CONFIG_POST & CONFIG_SYS_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
OpenPOWER on IntegriCloud