85 lines
2.2 KiB
C
85 lines
2.2 KiB
C
|
/*
|
||
|
* 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 user_disable_single_step(struct task_struct *child)
|
||
|
{
|
||
|
*(unsigned short *)(child->thread.esp0 + h8300_register_offset[PT_EXR]) &= ~EXR_TRACE;
|
||
|
}
|
||
|
|
||
|
/* enable singlestep */
|
||
|
void user_enable_single_step(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);
|
||
|
}
|
||
|
|