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). */
23static 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 */
30long 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 */
44int 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 */
68void 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 */
74void h8300_enable_trace(struct task_struct *child)
75{
76	*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE;
77}
78
79asmlinkage void trace_trap(unsigned long bp)
80{
81	(void)bp;
82	force_sig(SIGTRAP,current);
83}
84