OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [powerpc/] [lib/] [sstep.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * Single-step support.
3
 *
4
 * Copyright (C) 2004 Paul Mackerras <paulus@au.ibm.com>, IBM
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version
9
 * 2 of the License, or (at your option) any later version.
10
 */
11
#include <linux/kernel.h>
12
#include <linux/kprobes.h>
13
#include <linux/ptrace.h>
14
#include <asm/sstep.h>
15
#include <asm/processor.h>
16
 
17
extern char system_call_common[];
18
 
19
#ifdef CONFIG_PPC64
20
/* Bits in SRR1 that are copied from MSR */
21
#define MSR_MASK        0xffffffff87c0ffffUL
22
#else
23
#define MSR_MASK        0x87c0ffff
24
#endif
25
 
26
/*
27
 * Determine whether a conditional branch instruction would branch.
28
 */
29
static int __kprobes branch_taken(unsigned int instr, struct pt_regs *regs)
30
{
31
        unsigned int bo = (instr >> 21) & 0x1f;
32
        unsigned int bi;
33
 
34
        if ((bo & 4) == 0) {
35
                /* decrement counter */
36
                --regs->ctr;
37
                if (((bo >> 1) & 1) ^ (regs->ctr == 0))
38
                        return 0;
39
        }
40
        if ((bo & 0x10) == 0) {
41
                /* check bit from CR */
42
                bi = (instr >> 16) & 0x1f;
43
                if (((regs->ccr >> (31 - bi)) & 1) != ((bo >> 3) & 1))
44
                        return 0;
45
        }
46
        return 1;
47
}
48
 
49
/*
50
 * Emulate instructions that cause a transfer of control.
51
 * Returns 1 if the step was emulated, 0 if not,
52
 * or -1 if the instruction is one that should not be stepped,
53
 * such as an rfid, or a mtmsrd that would clear MSR_RI.
54
 */
55
int __kprobes emulate_step(struct pt_regs *regs, unsigned int instr)
56
{
57
        unsigned int opcode, rs, rb, rd, spr;
58
        unsigned long int imm;
59
 
60
        opcode = instr >> 26;
61
        switch (opcode) {
62
        case 16:        /* bc */
63
                imm = (signed short)(instr & 0xfffc);
64
                if ((instr & 2) == 0)
65
                        imm += regs->nip;
66
                regs->nip += 4;
67
                if ((regs->msr & MSR_SF) == 0)
68
                        regs->nip &= 0xffffffffUL;
69
                if (instr & 1)
70
                        regs->link = regs->nip;
71
                if (branch_taken(instr, regs))
72
                        regs->nip = imm;
73
                return 1;
74
#ifdef CONFIG_PPC64
75
        case 17:        /* sc */
76
                /*
77
                 * N.B. this uses knowledge about how the syscall
78
                 * entry code works.  If that is changed, this will
79
                 * need to be changed also.
80
                 */
81
                regs->gpr[9] = regs->gpr[13];
82
                regs->gpr[11] = regs->nip + 4;
83
                regs->gpr[12] = regs->msr & MSR_MASK;
84
                regs->gpr[13] = (unsigned long) get_paca();
85
                regs->nip = (unsigned long) &system_call_common;
86
                regs->msr = MSR_KERNEL;
87
                return 1;
88
#endif
89
        case 18:        /* b */
90
                imm = instr & 0x03fffffc;
91
                if (imm & 0x02000000)
92
                        imm -= 0x04000000;
93
                if ((instr & 2) == 0)
94
                        imm += regs->nip;
95
                if (instr & 1) {
96
                        regs->link = regs->nip + 4;
97
                        if ((regs->msr & MSR_SF) == 0)
98
                                regs->link &= 0xffffffffUL;
99
                }
100
                if ((regs->msr & MSR_SF) == 0)
101
                        imm &= 0xffffffffUL;
102
                regs->nip = imm;
103
                return 1;
104
        case 19:
105
                switch (instr & 0x7fe) {
106
                case 0x20:      /* bclr */
107
                case 0x420:     /* bcctr */
108
                        imm = (instr & 0x400)? regs->ctr: regs->link;
109
                        regs->nip += 4;
110
                        if ((regs->msr & MSR_SF) == 0) {
111
                                regs->nip &= 0xffffffffUL;
112
                                imm &= 0xffffffffUL;
113
                        }
114
                        if (instr & 1)
115
                                regs->link = regs->nip;
116
                        if (branch_taken(instr, regs))
117
                                regs->nip = imm;
118
                        return 1;
119
                case 0x24:      /* rfid, scary */
120
                        return -1;
121
                }
122
        case 31:
123
                rd = (instr >> 21) & 0x1f;
124
                switch (instr & 0x7fe) {
125
                case 0xa6:      /* mfmsr */
126
                        regs->gpr[rd] = regs->msr & MSR_MASK;
127
                        regs->nip += 4;
128
                        if ((regs->msr & MSR_SF) == 0)
129
                                regs->nip &= 0xffffffffUL;
130
                        return 1;
131
                case 0x124:     /* mtmsr */
132
                        imm = regs->gpr[rd];
133
                        if ((imm & MSR_RI) == 0)
134
                                /* can't step mtmsr that would clear MSR_RI */
135
                                return -1;
136
                        regs->msr = imm;
137
                        regs->nip += 4;
138
                        return 1;
139
#ifdef CONFIG_PPC64
140
                case 0x164:     /* mtmsrd */
141
                        /* only MSR_EE and MSR_RI get changed if bit 15 set */
142
                        /* mtmsrd doesn't change MSR_HV and MSR_ME */
143
                        imm = (instr & 0x10000)? 0x8002: 0xefffffffffffefffUL;
144
                        imm = (regs->msr & MSR_MASK & ~imm)
145
                                | (regs->gpr[rd] & imm);
146
                        if ((imm & MSR_RI) == 0)
147
                                /* can't step mtmsrd that would clear MSR_RI */
148
                                return -1;
149
                        regs->msr = imm;
150
                        regs->nip += 4;
151
                        if ((imm & MSR_SF) == 0)
152
                                regs->nip &= 0xffffffffUL;
153
                        return 1;
154
#endif
155
                case 0x26:      /* mfcr */
156
                        regs->gpr[rd] = regs->ccr;
157
                        regs->gpr[rd] &= 0xffffffffUL;
158
                        goto mtspr_out;
159
                case 0x2a6:     /* mfspr */
160
                        spr = (instr >> 11) & 0x3ff;
161
                        switch (spr) {
162
                        case 0x20:      /* mfxer */
163
                                regs->gpr[rd] = regs->xer;
164
                                regs->gpr[rd] &= 0xffffffffUL;
165
                                goto mtspr_out;
166
                        case 0x100:     /* mflr */
167
                                regs->gpr[rd] = regs->link;
168
                                goto mtspr_out;
169
                        case 0x120:     /* mfctr */
170
                                regs->gpr[rd] = regs->ctr;
171
                                goto mtspr_out;
172
                        }
173
                        break;
174
                case 0x378:     /* orx */
175
                        rs = (instr >> 21) & 0x1f;
176
                        rb = (instr >> 11) & 0x1f;
177
                        if (rs == rb) {         /* mr */
178
                                rd = (instr >> 16) & 0x1f;
179
                                regs->gpr[rd] = regs->gpr[rs];
180
                                goto mtspr_out;
181
                        }
182
                        break;
183
                case 0x3a6:     /* mtspr */
184
                        spr = (instr >> 11) & 0x3ff;
185
                        switch (spr) {
186
                        case 0x20:      /* mtxer */
187
                                regs->xer = (regs->gpr[rd] & 0xffffffffUL);
188
                                goto mtspr_out;
189
                        case 0x100:     /* mtlr */
190
                                regs->link = regs->gpr[rd];
191
                                goto mtspr_out;
192
                        case 0x120:     /* mtctr */
193
                                regs->ctr = regs->gpr[rd];
194
mtspr_out:
195
                                regs->nip += 4;
196
                                return 1;
197
                        }
198
                }
199
        }
200
        return 0;
201
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.