Linux-2.6.12-rc2
[linux-3.10.git] / arch / h8300 / platform / h8s / ptrace_h8s.c
1 /*
2  *  linux/arch/h8300/platform/h8s/ptrace_h8s.c
3  *    ptrace cpu depend helper functions
4  *
5  *  Yoshinori Sato <ysato@users.sourceforge.jp>
6  *
7  * This file is subject to the terms and conditions of the GNU General
8  * Public License.  See the file COPYING in the main directory of
9  * this archive for more details.
10  */
11
12 #include <linux/linkage.h>
13 #include <linux/sched.h>
14 #include <linux/errno.h>
15 #include <asm/ptrace.h>
16
17 #define CCR_MASK  0x6f
18 #define EXR_TRACE 0x80
19
20 /* Mapping from PT_xxx to the stack offset at which the register is
21    saved.  Notice that usp has no stack-slot and needs to be treated
22    specially (see get_reg/put_reg below). */
23 static const int h8300_register_offset[] = {
24         PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
25         PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0),
26         PT_REG(ccr), PT_REG(pc),  0,           PT_REG(exr)
27 };
28
29 /* read register */
30 long h8300_get_reg(struct task_struct *task, int regno)
31 {
32         switch (regno) {
33         case PT_USP:
34                 return task->thread.usp + sizeof(long)*2 + 2;
35         case PT_CCR:
36         case PT_EXR:
37             return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
38         default:
39             return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]);
40         }
41 }
42
43 /* write register */
44 int h8300_put_reg(struct task_struct *task, int regno, unsigned long data)
45 {
46         unsigned short oldccr;
47         switch (regno) {
48         case PT_USP:
49                 task->thread.usp = data - sizeof(long)*2 - 2;
50         case PT_CCR:
51                 oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
52                 oldccr &= ~CCR_MASK;
53                 data &= CCR_MASK;
54                 data |= oldccr;
55                 *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
56                 break;
57         case PT_EXR:
58                 /* exr modify not support */
59                 return -EIO;
60         default:
61                 *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
62                 break;
63         }
64         return 0;
65 }
66
67 /* disable singlestep */
68 void h8300_disable_trace(struct task_struct *child)
69 {
70         *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE;
71 }
72
73 /* enable singlestep */
74 void h8300_enable_trace(struct task_struct *child)
75 {
76         *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE;
77 }
78
79 asmlinkage void trace_trap(unsigned long bp)
80 {
81         (void)bp;
82         force_sig(SIGTRAP,current);
83 }
84