1 /* 2 * Copyright (C) 2016-2017 Andes Technology, Inc. 3 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball. 4 */ 5 6 #ifndef _LINUX_NDS32_SYSDEP_H 7 #define _LINUX_NDS32_SYSDEP_H 1 8 9 #include <common/sysdep.h> 10 11 #ifdef __ASSEMBLER__ 12 /* Define an entry point visible from C. */ 13 # ifdef PIC 14 # define ENTRY(name) \ 15 .pic \ 16 .align 2; \ 17 .globl C_SYMBOL_NAME(name); \ 18 .func C_SYMBOL_NAME(name); \ 19 .type C_SYMBOL_NAME(name), @function; \ 20 C_SYMBOL_NAME(name): \ 21 cfi_startproc; 22 23 # else 24 # define ENTRY(name) \ 25 .align 2; \ 26 .globl C_SYMBOL_NAME(name); \ 27 .func C_SYMBOL_NAME(name); \ 28 .type C_SYMBOL_NAME(name), @function; \ 29 C_SYMBOL_NAME(name): \ 30 cfi_startproc; 31 # endif 32 33 #undef END 34 #define END(name) \ 35 cfi_endproc; \ 36 .endfunc; \ 37 .size C_SYMBOL_NAME(name), .-C_SYMBOL_NAME(name) 38 39 /* If compiled for profiling, call `mcount' at the start of each function. */ 40 # ifdef HAVE_ELF 41 #undef NO_UNDERSCORES 42 #define NO_UNDERSCORES 43 # endif 44 45 # ifdef NO_UNDERSCORES 46 #define syscall_error __syscall_error 47 # endif 48 49 #define SYS_ify(syscall_name) (__NR_##syscall_name) 50 51 #define __do_syscall(syscall_name) \ 52 syscall SYS_ify(syscall_name); 53 54 # ifdef PIC 55 # define PSEUDO(name, syscall_name, args) \ 56 .pic; \ 57 .align 2; \ 58 99: mfusr $r15, $PC; \ 59 sethi $r1, hi20(_GLOBAL_OFFSET_TABLE_ + 4); \ 60 ori $r1, $r1, lo12(_GLOBAL_OFFSET_TABLE_ + 8); \ 61 add $r1, $r15, $r1; \ 62 sethi $r15, hi20(SYSCALL_ERROR@PLT); \ 63 ori $r15, $r15, lo12(SYSCALL_ERROR@PLT); \ 64 add $r15, $r15, $r1; \ 65 jr $r15; \ 66 nop; \ 67 ENTRY(name); \ 68 __do_syscall(syscall_name); \ 69 bgez $r0, 2f; \ 70 sltsi $r1, $r0, -4096; \ 71 beqz $r1, 99b; \ 72 2: 73 # else 74 # define PSEUDO(name, syscall_name, args) \ 75 .align 2; \ 76 99: j SYSCALL_ERROR; \ 77 nop; \ 78 ENTRY(name); \ 79 __do_syscall(syscall_name); \ 80 bgez $r0, 2f; \ 81 sltsi $r1, $r0, -4096; \ 82 beqz $r1, 99b; \ 83 2: 84 # endif 85 86 87 #define PSEUDO_NOERRNO(name, syscall_name, args) \ 88 ENTRY(name); \ 89 __do_syscall(syscall_name); 90 91 #undef PSEUDO_END 92 #define PSEUDO_END(sym) \ 93 SYSCALL_ERROR_HANDLER \ 94 END(sym) 95 96 #undef PSEUDO_END_ERRVAL 97 #define PSEUDO_END_ERRVAL(sym) END(sym) 98 99 #define PSEUDO_ERRVAL(name, syscall_name, args) PSEUDO_NOERRNO(name, syscall_name, args) 100 101 #define ret_ERRVAL ret 102 103 #define ret_NOERRNO ret 104 #if defined NOT_IN_libc 105 #define SYSCALL_ERROR __local_syscall_error 106 #ifdef PIC 107 #define SYSCALL_ERROR_HANDLER \ 108 __local_syscall_error: \ 109 pushm $gp, $lp; \ 110 cfi_adjust_cfa_offset(8) \ 111 cfi_rel_offset(gp, 0) \ 112 cfi_rel_offset(lp, 4) \ 113 mfusr $r15, $PC; \ 114 sethi $gp, hi20(_GLOBAL_OFFSET_TABLE_+4); \ 115 ori $gp, $gp, lo12(_GLOBAL_OFFSET_TABLE_+8); \ 116 add $gp, $gp, $r15; \ 117 neg $r0, $r0; \ 118 push $r0; \ 119 cfi_adjust_cfa_offset(4) \ 120 cfi_rel_offset(r0, 0) \ 121 addi $sp, $sp, -4; \ 122 bal C_SYMBOL_NAME(__errno_location@PLT); \ 123 addi $sp, $sp, 4; \ 124 pop $r1; \ 125 cfi_adjust_cfa_offset(-4); \ 126 cfi_restore(r1); \ 127 swi $r1, [$r0]; \ 128 li $r0, -1; \ 129 popm $gp, $lp; \ 130 cfi_adjust_cfa_offset(-8); \ 131 cfi_restore(lp); \ 132 cfi_restore(gp); \ 133 1: ret; 134 #else 135 #define SYSCALL_ERROR_HANDLER \ 136 __local_syscall_error: \ 137 push $lp; \ 138 cfi_adjust_cfa_offset(4) \ 139 cfi_rel_offset(lp, 0) \ 140 neg $r0, $r0; \ 141 push $r0; \ 142 cfi_adjust_cfa_offset(4) \ 143 cfi_rel_offset(r0, 0) \ 144 addi $sp, $sp, -4; \ 145 bal C_SYMBOL_NAME(__errno_location); \ 146 addi $sp, $sp, 4; \ 147 pop $r1; \ 148 cfi_adjust_cfa_offset(-4); \ 149 cfi_restore(r1); \ 150 swi $r1, [$r0]; \ 151 li $r0, -1; \ 152 pop $lp; \ 153 cfi_adjust_cfa_offset(-4); \ 154 cfi_restore(lp); \ 155 ret; 156 #endif 157 158 #else 159 #define SYSCALL_ERROR_HANDLER 160 #define SYSCALL_ERROR __syscall_error 161 #endif 162 163 #endif /* __ASSEMBLER__ */ 164 #endif //_LINUX_NDS32_SYSDEP_H 165