aboutsummaryrefslogtreecommitdiff
path: root/arch/h8300/platform/h8s/ptrace_h8s.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/h8300/platform/h8s/ptrace_h8s.c')
-rw-r--r--arch/h8300/platform/h8s/ptrace_h8s.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/arch/h8300/platform/h8s/ptrace_h8s.c b/arch/h8300/platform/h8s/ptrace_h8s.c
new file mode 100644
index 00000000000..e8cd46f9255
--- /dev/null
+++ b/arch/h8300/platform/h8s/ptrace_h8s.c
@@ -0,0 +1,84 @@
+/*
+ * linux/arch/h8300/platform/h8s/ptrace_h8s.c
+ * ptrace cpu depend helper functions
+ *
+ * Yoshinori Sato <ysato@users.sourceforge.jp>
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License. See the file COPYING in the main directory of
+ * this archive for more details.
+ */
+
+#include <linux/linkage.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <asm/ptrace.h>
+
+#define CCR_MASK 0x6f
+#define EXR_TRACE 0x80
+
+/* Mapping from PT_xxx to the stack offset at which the register is
+ saved. Notice that usp has no stack-slot and needs to be treated
+ specially (see get_reg/put_reg below). */
+static const int h8300_register_offset[] = {
+ PT_REG(er1), PT_REG(er2), PT_REG(er3), PT_REG(er4),
+ PT_REG(er5), PT_REG(er6), PT_REG(er0), PT_REG(orig_er0),
+ PT_REG(ccr), PT_REG(pc), 0, PT_REG(exr)
+};
+
+/* read register */
+long h8300_get_reg(struct task_struct *task, int regno)
+{
+ switch (regno) {
+ case PT_USP:
+ return task->thread.usp + sizeof(long)*2 + 2;
+ case PT_CCR:
+ case PT_EXR:
+ return *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
+ default:
+ return *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]);
+ }
+}
+
+/* write register */
+int h8300_put_reg(struct task_struct *task, int regno, unsigned long data)
+{
+ unsigned short oldccr;
+ switch (regno) {
+ case PT_USP:
+ task->thread.usp = data - sizeof(long)*2 - 2;
+ case PT_CCR:
+ oldccr = *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]);
+ oldccr &= ~CCR_MASK;
+ data &= CCR_MASK;
+ data |= oldccr;
+ *(unsigned short *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
+ break;
+ case PT_EXR:
+ /* exr modify not support */
+ return -EIO;
+ default:
+ *(unsigned long *)(task->thread.esp0 + h8300_register_offset[regno]) = data;
+ break;
+ }
+ return 0;
+}
+
+/* disable singlestep */
+void h8300_disable_trace(struct task_struct *child)
+{
+ *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE;
+}
+
+/* enable singlestep */
+void h8300_enable_trace(struct task_struct *child)
+{
+ *(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) |= EXR_TRACE;
+}
+
+asmlinkage void trace_trap(unsigned long bp)
+{
+ (void)bp;
+ force_sig(SIGTRAP,current);
+}
+