Blackfin: add support for the DBG (debug output) pseudo insn
authorRobin Getz <robin.getz@analog.com>
Sun, 28 Mar 2010 12:50:53 +0000 (12:50 +0000)
committerMike Frysinger <vapier@gentoo.org>
Sat, 22 May 2010 18:19:05 +0000 (14:19 -0400)
Another pseudo insn used by Blackfin simulators.  Also factor some now
common register lookup code out of the DBGA handlers.

Signed-off-by: Robin Getz <robin.getz@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
arch/blackfin/include/asm/pseudo_instructions.h
arch/blackfin/kernel/pseudodbg.c
arch/blackfin/kernel/traps.c

index 7173719fb531f0769dfae064dac040a1b880b3f4..b00adfa08169ab5ab5e59efdd728a2b7810b953a 100644 (file)
@@ -13,5 +13,6 @@
 #include <asm/ptrace.h>
 
 extern bool execute_pseudodbg_assert(struct pt_regs *fp, unsigned int opcode);
+extern bool execute_pseudodbg(struct pt_regs *fp, unsigned int opcode);
 
 #endif
index 4474b8db350168ac4d078eb2493c17d7a33a8690..a5a4636124aa0c8ef8bb35e14c3944690487b4c3 100644 (file)
@@ -9,6 +9,30 @@
 #include <linux/kernel.h>
 #include <linux/ptrace.h>
 
+/*
+ * Unfortunately, the pt_regs structure is not laid out the same way as the
+ * hardware register file, so we need to do some fix ups.
+ */
+static bool fix_up_reg(struct pt_regs *fp, long *value, int grp, int reg)
+{
+       long *val = &fp->r0;
+
+       /* Only do Dregs and Pregs for now */
+       if (grp > 1)
+               return false;
+
+       if (grp == 0 || (grp == 1 && reg < 6))
+               val -= (reg + 8 * grp);
+       else if (grp == 1 && reg == 6)
+               val = &fp->usp;
+       else if (grp == 1 && reg == 7)
+               val = &fp->fp;
+
+       *value = *val;
+       return true;
+
+}
+
 #define PseudoDbg_Assert_opcode         0xf0000000
 #define PseudoDbg_Assert_expected_bits  0
 #define PseudoDbg_Assert_expected_mask  0xffff
 #define PseudoDbg_Assert_code_bits      27
 #define PseudoDbg_Assert_code_mask      0x1f
 
+/*
+ * DBGA - debug assert
+ */
 bool execute_pseudodbg_assert(struct pt_regs *fp, unsigned int opcode)
 {
        int expected = ((opcode >> PseudoDbg_Assert_expected_bits) & PseudoDbg_Assert_expected_mask);
        int dbgop    = ((opcode >> (PseudoDbg_Assert_dbgop_bits)) & PseudoDbg_Assert_dbgop_mask);
        int grp      = ((opcode >> (PseudoDbg_Assert_grp_bits)) & PseudoDbg_Assert_grp_mask);
        int regtest  = ((opcode >> (PseudoDbg_Assert_regtest_bits)) & PseudoDbg_Assert_regtest_mask);
-       long *value = &fp->r0;
+       long value;
 
        if ((opcode & 0xFF000000) != PseudoDbg_Assert_opcode)
                return false;
 
-       /* Only do Dregs and Pregs for now */
-       if (grp > 1)
+       if (!fix_up_reg(fp, &value, grp, regtest))
                return false;
 
-       /*
-        * Unfortunately, the pt_regs structure is not laid out the same way as the
-        * hardware register file, so we need to do some fix ups.
-        */
-       if (grp == 0 || (grp == 1 && regtest < 6))
-               value -= (regtest + 8 * grp);
-       else if (grp == 1 && regtest == 6)
-               value = &fp->usp;
-       else if (grp == 1 && regtest == 7)
-               value = &fp->fp;
-
        if (dbgop == 0 || dbgop == 2) {
                /* DBGA ( regs_lo , uimm16 ) */
                /* DBGAL ( regs , uimm16 ) */
-               if (expected != (*value & 0xFFFF)) {
+               if (expected != (value & 0xFFFF)) {
                        pr_notice("DBGA (%s%i.L,0x%x) failure, got 0x%x\n", grp ? "P" : "R",
-                               regtest, expected, (unsigned int)(*value & 0xFFFF));
+                               regtest, expected, (unsigned int)(value & 0xFFFF));
                        return false;
                }
 
        } else if (dbgop == 1 || dbgop == 3) {
                /* DBGA ( regs_hi , uimm16 ) */
                /* DBGAH ( regs , uimm16 ) */
-               if (expected != ((*value >> 16) & 0xFFFF)) {
+               if (expected != ((value >> 16) & 0xFFFF)) {
                        pr_notice("DBGA (%s%i.H,0x%x) failure, got 0x%x\n", grp ? "P" : "R",
-                               regtest, expected, (unsigned int)((*value >> 16) & 0xFFFF));
+                               regtest, expected, (unsigned int)((value >> 16) & 0xFFFF));
                        return false;
                }
        }
@@ -71,3 +86,38 @@ bool execute_pseudodbg_assert(struct pt_regs *fp, unsigned int opcode)
        fp->pc += 4;
        return true;
 }
+
+#define PseudoDbg_opcode        0xf8000000
+#define PseudoDbg_reg_bits      0
+#define PseudoDbg_reg_mask      0x7
+#define PseudoDbg_grp_bits      3
+#define PseudoDbg_grp_mask      0x7
+#define PseudoDbg_fn_bits       6
+#define PseudoDbg_fn_mask       0x3
+#define PseudoDbg_code_bits     8
+#define PseudoDbg_code_mask     0xff
+
+/*
+ * DBG - debug (dump a register value out)
+ */
+bool execute_pseudodbg(struct pt_regs *fp, unsigned int opcode)
+{
+       int grp, fn, reg;
+       long value;
+
+       if ((opcode & 0xFF000000) != PseudoDbg_opcode)
+               return false;
+
+       opcode >>= 16;
+       grp = ((opcode >> PseudoDbg_grp_bits) & PseudoDbg_reg_mask);
+       fn  = ((opcode >> PseudoDbg_fn_bits)  & PseudoDbg_fn_mask);
+       reg = ((opcode >> PseudoDbg_reg_bits) & PseudoDbg_reg_mask);
+
+       if (!fix_up_reg(fp, &value, grp, reg))
+               return false;
+
+       pr_notice("DBG %s%d = %08lx\n", grp ? "P" : "R", reg, value);
+
+       fp->pc += 2;
+       return true;
+}
index 9369836365bb72a2573774b84755868de4923f76..59c1df75e4de9519d61070142b62f3b1eb90ef5a 100644 (file)
@@ -213,6 +213,8 @@ asmlinkage notrace void trap_c(struct pt_regs *fp)
                if (!kernel_mode_regs(fp) && get_instruction(&opcode, (unsigned short *)fp->pc)) {
                        if (execute_pseudodbg_assert(fp, opcode))
                                goto traps_done;
+                       if (execute_pseudodbg(fp, opcode))
+                               goto traps_done;
                }
 #endif
                info.si_code = ILL_ILLOPC;