1 #ifndef __ASM_SH_SYSCALL_32_H 2 #define __ASM_SH_SYSCALL_32_H 3 4 #include <linux/kernel.h> 5 #include <linux/sched.h> 6 #include <asm/ptrace.h> 7 8 /* The system call number is given by the user in %g1 */ 9 static inline long syscall_get_nr(struct task_struct *task, 10 struct pt_regs *regs) 11 { 12 return (regs->tra >= 0) ? regs->regs[3] : -1L; 13 } 14 15 static inline void syscall_rollback(struct task_struct *task, 16 struct pt_regs *regs) 17 { 18 /* 19 * XXX: This needs some thought. On SH we don't 20 * save away the original r0 value anywhere. 21 */ 22 } 23 24 static inline bool syscall_has_error(struct pt_regs *regs) 25 { 26 return (regs->sr & 0x1) ? true : false; 27 } 28 static inline void syscall_set_error(struct pt_regs *regs) 29 { 30 regs->sr |= 0x1; 31 } 32 static inline void syscall_clear_error(struct pt_regs *regs) 33 { 34 regs->sr &= ~0x1; 35 } 36 37 static inline long syscall_get_error(struct task_struct *task, 38 struct pt_regs *regs) 39 { 40 return syscall_has_error(regs) ? regs->regs[0] : 0; 41 } 42 43 static inline long syscall_get_return_value(struct task_struct *task, 44 struct pt_regs *regs) 45 { 46 return regs->regs[0]; 47 } 48 49 static inline void syscall_set_return_value(struct task_struct *task, 50 struct pt_regs *regs, 51 int error, long val) 52 { 53 if (error) { 54 syscall_set_error(regs); 55 regs->regs[0] = -error; 56 } else { 57 syscall_clear_error(regs); 58 regs->regs[0] = val; 59 } 60 } 61 62 static inline void syscall_get_arguments(struct task_struct *task, 63 struct pt_regs *regs, 64 unsigned int i, unsigned int n, 65 unsigned long *args) 66 { 67 /* 68 * Do this simply for now. If we need to start supporting 69 * fetching arguments from arbitrary indices, this will need some 70 * extra logic. Presently there are no in-tree users that depend 71 * on this behaviour. 72 */ 73 BUG_ON(i); 74 75 /* Argument pattern is: R4, R5, R6, R7, R0, R1 */ 76 switch (n) { 77 case 6: args[5] = regs->regs[1]; 78 case 5: args[4] = regs->regs[0]; 79 case 4: args[3] = regs->regs[7]; 80 case 3: args[2] = regs->regs[6]; 81 case 2: args[1] = regs->regs[5]; 82 case 1: args[0] = regs->regs[4]; 83 break; 84 default: 85 BUG(); 86 } 87 } 88 89 static inline void syscall_set_arguments(struct task_struct *task, 90 struct pt_regs *regs, 91 unsigned int i, unsigned int n, 92 const unsigned long *args) 93 { 94 /* Same note as above applies */ 95 BUG_ON(i); 96 97 switch (n) { 98 case 6: regs->regs[1] = args[5]; 99 case 5: regs->regs[0] = args[4]; 100 case 4: regs->regs[7] = args[3]; 101 case 3: regs->regs[6] = args[2]; 102 case 2: regs->regs[5] = args[1]; 103 case 1: regs->regs[4] = args[0]; 104 break; 105 default: 106 BUG(); 107 } 108 } 109 110 #endif /* __ASM_SH_SYSCALL_32_H */ 111