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 */
h8300_get_reg(struct task_struct * task,int regno)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 */
h8300_put_reg(struct task_struct * task,int regno,unsigned long data)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 */
user_disable_single_step(struct task_struct * child)68 void user_disable_single_step(struct task_struct *child)
69 {
70 	*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE;
71 }
72 
73 /* enable singlestep */
user_enable_single_step(struct task_struct * child)74 void user_enable_single_step(struct task_struct *child)
75 {
76 	*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE;
77 }
78 
trace_trap(unsigned long bp)79 asmlinkage void trace_trap(unsigned long bp)
80 {
81 	(void)bp;
82 	force_sig(SIGTRAP,current);
83 }
84 
85