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