blob: a5a4636124aa0c8ef8bb35e14c3944690487b4c3 [file] [log] [blame]
Robin Getz6ce3e9c2010-03-16 14:40:17 +00001/* 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
Robin Getzdc89d972010-03-28 12:50:53 +000012/*
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 */
16static 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
Robin Getz6ce3e9c2010-03-16 14:40:17 +000036#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
Robin Getzdc89d972010-03-28 12:50:53 +000050/*
51 * DBGA - debug assert
52 */
Robin Getz6ce3e9c2010-03-16 14:40:17 +000053bool 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);
Robin Getzdc89d972010-03-28 12:50:53 +000059 long value;
Robin Getz6ce3e9c2010-03-16 14:40:17 +000060
61 if ((opcode & 0xFF000000) != PseudoDbg_Assert_opcode)
62 return false;
63
Robin Getzdc89d972010-03-28 12:50:53 +000064 if (!fix_up_reg(fp, &value, grp, regtest))
Robin Getz6ce3e9c2010-03-16 14:40:17 +000065 return false;
66
Robin Getz6ce3e9c2010-03-16 14:40:17 +000067 if (dbgop == 0 || dbgop == 2) {
68 /* DBGA ( regs_lo , uimm16 ) */
69 /* DBGAL ( regs , uimm16 ) */
Robin Getzdc89d972010-03-28 12:50:53 +000070 if (expected != (value & 0xFFFF)) {
Robin Getz6ce3e9c2010-03-16 14:40:17 +000071 pr_notice("DBGA (%s%i.L,0x%x) failure, got 0x%x\n", grp ? "P" : "R",
Robin Getzdc89d972010-03-28 12:50:53 +000072 regtest, expected, (unsigned int)(value & 0xFFFF));
Robin Getz6ce3e9c2010-03-16 14:40:17 +000073 return false;
74 }
75
76 } else if (dbgop == 1 || dbgop == 3) {
77 /* DBGA ( regs_hi , uimm16 ) */
78 /* DBGAH ( regs , uimm16 ) */
Robin Getzdc89d972010-03-28 12:50:53 +000079 if (expected != ((value >> 16) & 0xFFFF)) {
Robin Getz6ce3e9c2010-03-16 14:40:17 +000080 pr_notice("DBGA (%s%i.H,0x%x) failure, got 0x%x\n", grp ? "P" : "R",
Robin Getzdc89d972010-03-28 12:50:53 +000081 regtest, expected, (unsigned int)((value >> 16) & 0xFFFF));
Robin Getz6ce3e9c2010-03-16 14:40:17 +000082 return false;
83 }
84 }
85
86 fp->pc += 4;
87 return true;
88}
Robin Getzdc89d972010-03-28 12:50:53 +000089
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 */
103bool 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}