|  | /* | 
|  | *  linux/arch/h8300/platform/h8s/ptrace_h8s.c | 
|  | *    ptrace cpu depend helper functions | 
|  | * | 
|  | *  Yoshinori Sato <[email protected]> | 
|  | * | 
|  | * 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); | 
|  | } | 
|  |  |