]> Pileus Git - ~andy/linux/blob - arch/blackfin/kernel/pseudodbg.c
Blackfin: add support for the DBG (debug output) pseudo insn
[~andy/linux] / arch / blackfin / kernel / pseudodbg.c
1 /* The fake debug assert instructions
2  *
3  * Copyright 2010 Analog Devices Inc.
4  *
5  * Licensed under the GPL-2 or later
6  */
7
8 #include <linux/types.h>
9 #include <linux/kernel.h>
10 #include <linux/ptrace.h>
11
12 /*
13  * Unfortunately, the pt_regs structure is not laid out the same way as the
14  * hardware register file, so we need to do some fix ups.
15  */
16 static bool fix_up_reg(struct pt_regs *fp, long *value, int grp, int reg)
17 {
18         long *val = &fp->r0;
19
20         /* Only do Dregs and Pregs for now */
21         if (grp > 1)
22                 return false;
23
24         if (grp == 0 || (grp == 1 && reg < 6))
25                 val -= (reg + 8 * grp);
26         else if (grp == 1 && reg == 6)
27                 val = &fp->usp;
28         else if (grp == 1 && reg == 7)
29                 val = &fp->fp;
30
31         *value = *val;
32         return true;
33
34 }
35
36 #define PseudoDbg_Assert_opcode         0xf0000000
37 #define PseudoDbg_Assert_expected_bits  0
38 #define PseudoDbg_Assert_expected_mask  0xffff
39 #define PseudoDbg_Assert_regtest_bits   16
40 #define PseudoDbg_Assert_regtest_mask   0x7
41 #define PseudoDbg_Assert_grp_bits       19
42 #define PseudoDbg_Assert_grp_mask       0x7
43 #define PseudoDbg_Assert_dbgop_bits     22
44 #define PseudoDbg_Assert_dbgop_mask     0x3
45 #define PseudoDbg_Assert_dontcare_bits  24
46 #define PseudoDbg_Assert_dontcare_mask  0x7
47 #define PseudoDbg_Assert_code_bits      27
48 #define PseudoDbg_Assert_code_mask      0x1f
49
50 /*
51  * DBGA - debug assert
52  */
53 bool execute_pseudodbg_assert(struct pt_regs *fp, unsigned int opcode)
54 {
55         int expected = ((opcode >> PseudoDbg_Assert_expected_bits) & PseudoDbg_Assert_expected_mask);
56         int dbgop    = ((opcode >> (PseudoDbg_Assert_dbgop_bits)) & PseudoDbg_Assert_dbgop_mask);
57         int grp      = ((opcode >> (PseudoDbg_Assert_grp_bits)) & PseudoDbg_Assert_grp_mask);
58         int regtest  = ((opcode >> (PseudoDbg_Assert_regtest_bits)) & PseudoDbg_Assert_regtest_mask);
59         long value;
60
61         if ((opcode & 0xFF000000) != PseudoDbg_Assert_opcode)
62                 return false;
63
64         if (!fix_up_reg(fp, &value, grp, regtest))
65                 return false;
66
67         if (dbgop == 0 || dbgop == 2) {
68                 /* DBGA ( regs_lo , uimm16 ) */
69                 /* DBGAL ( regs , uimm16 ) */
70                 if (expected != (value & 0xFFFF)) {
71                         pr_notice("DBGA (%s%i.L,0x%x) failure, got 0x%x\n", grp ? "P" : "R",
72                                 regtest, expected, (unsigned int)(value & 0xFFFF));
73                         return false;
74                 }
75
76         } else if (dbgop == 1 || dbgop == 3) {
77                 /* DBGA ( regs_hi , uimm16 ) */
78                 /* DBGAH ( regs , uimm16 ) */
79                 if (expected != ((value >> 16) & 0xFFFF)) {
80                         pr_notice("DBGA (%s%i.H,0x%x) failure, got 0x%x\n", grp ? "P" : "R",
81                                 regtest, expected, (unsigned int)((value >> 16) & 0xFFFF));
82                         return false;
83                 }
84         }
85
86         fp->pc += 4;
87         return true;
88 }
89
90 #define PseudoDbg_opcode        0xf8000000
91 #define PseudoDbg_reg_bits      0
92 #define PseudoDbg_reg_mask      0x7
93 #define PseudoDbg_grp_bits      3
94 #define PseudoDbg_grp_mask      0x7
95 #define PseudoDbg_fn_bits       6
96 #define PseudoDbg_fn_mask       0x3
97 #define PseudoDbg_code_bits     8
98 #define PseudoDbg_code_mask     0xff
99
100 /*
101  * DBG - debug (dump a register value out)
102  */
103 bool execute_pseudodbg(struct pt_regs *fp, unsigned int opcode)
104 {
105         int grp, fn, reg;
106         long value;
107
108         if ((opcode & 0xFF000000) != PseudoDbg_opcode)
109                 return false;
110
111         opcode >>= 16;
112         grp = ((opcode >> PseudoDbg_grp_bits) & PseudoDbg_reg_mask);
113         fn  = ((opcode >> PseudoDbg_fn_bits)  & PseudoDbg_fn_mask);
114         reg = ((opcode >> PseudoDbg_reg_bits) & PseudoDbg_reg_mask);
115
116         if (!fix_up_reg(fp, &value, grp, reg))
117                 return false;
118
119         pr_notice("DBG %s%d = %08lx\n", grp ? "P" : "R", reg, value);
120
121         fp->pc += 2;
122         return true;
123 }