1 /* Copyright (C) 2011-2018 Free Software Foundation, Inc.
2 
3    The GNU C Library is free software; you can redistribute it and/or
4    modify it under the terms of the GNU Lesser General Public
5    License as published by the Free Software Foundation; either
6    version 2.1 of the License, or (at your option) any later version.
7 
8    The GNU C Library is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11    Lesser General Public License for more details.
12 
13    You should have received a copy of the GNU Lesser General Public
14    License along with the GNU C Library.  If not, see
15    <http://www.gnu.org/licenses/>.  */
16 
17 #include <common/sysdep.h>
18 #include <bits/wordsize.h>
19 #include <arch/abi.h>
20 
21 #undef SYS_ify
22 #define SYS_ify(syscall_name)	__NR_##syscall_name
23 
24 #if defined __ASSEMBLER__
25 
26 /* Make use of .size directive.  */
27 #define ASM_SIZE_DIRECTIVE(name) .size name,.-name;
28 
29 /* Define an entry point visible from C.  */
30 #define	ENTRY(name)							      \
31   .globl C_SYMBOL_NAME(name);						      \
32   .type C_SYMBOL_NAME(name),@function;					      \
33   .align 8;								      \
34   C_LABEL(name)								      \
35   cfi_startproc;							      \
36 
37 #undef	END
38 #define END(name)							      \
39   cfi_endproc;								      \
40   ASM_SIZE_DIRECTIVE(name)
41 
42 /* Since C identifiers are not normally prefixed with an underscore
43    on this system, the asm identifier `syscall_error' intrudes on the
44    C name space.  Make sure we use an innocuous name.  */
45 #define	syscall_error	__syscall_error
46 
47 /* Local label name for asm code. */
48 #define L(name)		.L##name
49 
50 /* Specify the size in bytes of a machine register.  */
51 #define REGSIZE		8
52 
53 /* Provide "pointer-oriented" instruction variants.  These differ not
54    just for tilepro vs tilegx, but also for tilegx -m64 vs -m32.  */
55 #if __WORDSIZE == 32
56 #define ADD_PTR		addx
57 #define ADDI_PTR	addxi
58 #define ADDLI_PTR	addxli
59 #define LD_PTR		ld4s
60 #define ST_PTR		st4
61 #define SHL_PTR_ADD	shl2add
62 #else
63 #define ADD_PTR		add
64 #define ADDI_PTR	addi
65 #define ADDLI_PTR	addli
66 #define LD_PTR		LD
67 #define ST_PTR		ST
68 #define SHL_PTR_ADD	shl3add
69 #endif
70 
71 /* The actual implementation of doing a syscall. */
72 #define DO_CALL(syscall_name, args)                     \
73   moveli TREG_SYSCALL_NR_NAME, SYS_ify(syscall_name);	\
74   swint1
75 
76 /* TILE Linux returns the result in r0 (or a negative errno).
77    The kernel "owns" the code to decide if a given value is an error,
78    and puts errno in r1 if so, or otherwise zero.  */
79 #define	PSEUDO(name, syscall_name, args)		\
80   ENTRY	(name);						\
81   DO_CALL(syscall_name, args);				\
82   BNEZ r1, 0f
83 
84 #define ret  jrp lr
85 
86 #ifndef SHARED
87 /* For static code, on error jump to __syscall_error directly. */
88 # define SYSCALL_ERROR_NAME __syscall_error
89 #elif IS_IN_libc || IS_IN_libpthread
90 /* Use the internal name for libc/libpthread shared objects. */
91 # define SYSCALL_ERROR_NAME __GI___syscall_error
92 #else
93 /* Otherwise, on error do a full PLT jump. */
94 # define SYSCALL_ERROR_NAME plt(__syscall_error)
95 #endif
96 
97 #undef PSEUDO_END
98 #define	PSEUDO_END(name)				\
99 0:							\
100   j SYSCALL_ERROR_NAME;					\
101   END (name)
102 
103 #undef PSEUDO_NOERRNO
104 #define	PSEUDO_NOERRNO(name, syscall_name, args)	\
105   ENTRY	(name);						\
106   DO_CALL(syscall_name, args)
107 
108 #define ret_NOERRNO  jrp lr
109 
110 #undef PSEUDO_END_NOERRNO
111 #define	PSEUDO_END_NOERRNO(name) \
112   END (name)
113 
114 /* Convenience wrappers. */
115 #define SYSCALL__(name, args)   PSEUDO (__##name, name, args)
116 #define SYSCALL(name, args)   PSEUDO (name, name, args)
117 
118 #endif /* __ASSEMBLER__ */
119