summaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/csky/sysdep.h
blob: 2fcff684e6f379300dcddf21a9d725273d94843c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
#ifndef _LINUX_CSKY_SYSDEP_H
#define _LINUX_CSKY_SYSDEP_H 1

#include <common/sysdep.h>
#include <sys/syscall.h>

#undef	SYS_ify
#define	SYS_ify(name) (__NR_##name)

#ifdef __ASSEMBLER__

/* ELF uses byte-counts for .align, most others use log2 of count of bytes.  */
#define ALIGNARG(log2) log2
/* For ELF we need the `.type' directive to make shared libs work right.  */
#define ASM_TYPE_DIRECTIVE(name,typearg) .type name,%##typearg;
#define ASM_SIZE_DIRECTIVE(name) .size name,.-name

#define	ENTRY(name) \
  .globl C_SYMBOL_NAME(name); \
  ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),function) \
  .align ALIGNARG(4); \
  C_LABEL(name)

#undef END
#define END(name) ASM_SIZE_DIRECTIVE(name)

#undef	ret_ERRVAL
#define	ret_ERRVAL rts

#undef	PSEUDO_END
#define	PSEUDO_END(name) END(name)

#ifdef __PIC__
#define __GET_GB \
  bsr 1f; \
  1: lrw gb, 1b@GOTPC; \
  addu gb, lr;

/*
 * __JSR must be used with __GET_GB and SAVE_ARGS
 */
#define __JSR(symbol) \
  lrw a2, symbol@PLT; \
  add a2, gb; \
  ld.w a2, (a2); \
  jsr a2;

#define PSEUDO_ERRJMP \
  subi sp, 8; \
  st.w lr, (sp); \
  st.w gb, (sp, 4); \
  __GET_GB \
  lrw a2, __syscall_error@PLT; \
  addu a2, gb; \
  ld.w a2, (a2); \
  jsr a2; \
  ld.w lr, (sp); \
  ld.w gb, (sp, 4); \
  addi sp, 8; \
  rts;

#else /* __PIC__ */

#define __GET_GB
#define __JSR(symbol) jsri symbol;
#define PSEUDO_ERRJMP \
  subi	sp, 4; \
  stw	lr, (sp, 0); \
  jsri	__syscall_error; \
  ldw	lr, (sp, 0); \
  addi	sp, 4; \
  rts;

#endif /* __PIC__ */

#define PSEUDO_ERRVAL(name, syscall_name, args) \
  .text; \
  99: PSEUDO_ERRJMP; \
  ENTRY(name); \
  DO_CALL(syscall_name, args); \
  btsti	a0, 31; \
  bt 99b;

#undef PSEUDO_END_ERRVAL
#define PSEUDO_END_ERRVAL(name) \
  rts; \
  END(name)

/* DO_CALL */
#undef	DO_CALL
#ifdef	__CSKYABIV2__

#define	DO_CALL(syscall_name, args) \
  DOARGS_##args \
  mov	t0, r7; \
  lrw	r7, SYS_ify (syscall_name); \
  trap	0; \
  mov	r7, t0; \
  UNDOARGS_##args

#define DOARGS_0
#define DOARGS_1
#define DOARGS_2
#define DOARGS_3
#define DOARGS_4
#define DOARGS_5 subi sp, 4; st.w r4, (sp, 0); ld.w r4, (sp, 4);
#define DOARGS_6 subi sp, 8; stm r4-r5, (sp); ld.w r4, (sp, 8); ld.w r5, (sp, 12);

#define UNDOARGS_0
#define UNDOARGS_1
#define UNDOARGS_2
#define UNDOARGS_3
#define UNDOARGS_4
#define UNDOARGS_5 ld.w r4, (sp, 0); addi sp, 4;
#define UNDOARGS_6 ldm r4-r5, (sp); addi sp, 8;

#else /* __CSKYABIV2__ */

#define DO_CALL(syscall_name, args) \
  lrw  r1, SYS_ify (syscall_name); \
  trap 0;

#define DOARGS_0
#define DOARGS_1
#define DOARGS_2
#define DOARGS_3
#define DOARGS_4
#define DOARGS_5
#define DOARGS_6

#define UNDOARGS_0
#define UNDOARGS_1
#define UNDOARGS_2
#define UNDOARGS_3
#define UNDOARGS_4
#define UNDOARGS_5
#define UNDOARGS_6

#endif /* __CSKYABIV2__ */

/*
 * define DO_CALL_2, only ABIV2 need DO_CALL_2
 * to be quite different with DO_CALL, DO_CALL_2 need not save r7.
 */
#ifdef __CSKYABIV2__
#undef  DO_CALL_2
#define DO_CALL_2(syscall_name, args) \
  DOARGS2_##args; \
  lrw	r7, SYS_ify(syscall_name); \
  trap	0; \
  UNDOARGS2_##args
#undef  DOARGS2_0
#define DOARGS2_0

#undef  DOARGS2_1
#define DOARGS2_1 DOARGS2_0
#undef  DOARGS2_2
#define DOARGS2_2 DOARGS2_0
#undef  DOARGS2_3
#define DOARGS2_3 DOARGS2_0
#undef  DOARGS2_4
#define DOARGS2_4 DOARGS2_0
#undef  DOARGS2_5
#define DOARGS2_5 \
  subi sp, 8; \
  cfi_adjust_cfa_offset (8); \
  stw  r4, (sp, 0); \
  ldw  r4, (sp, 24)
#undef  DOARGS2_6
#define DOARGS2_6 \
  subi sp, 8; \
  cfi_adjust_cfa_offset (8); \
  stw  r4, (sp, 0); \
  stw  r5, (sp, 4); \
  ldw  r4, (sp, 24); \
  ldw  r5, (sp, 28)

#undef  UNDOARGS2_0
#define UNDOARGS2_0

#undef  UNDOARGS2_1
#define UNDOARGS2_1 UNDOARGS2_0
#undef  UNDOARGS2_2
#define UNDOARGS2_2 UNDOARGS2_0
#undef  UNDOARGS2_3
#define UNDOARGS2_3 UNDOARGS2_0
#undef  UNDOARGS2_4
#define UNDOARGS2_4 UNDOARGS2_0
#undef  UNDOARGS2_5
#define UNDOARGS2_5 \
  ldw  r4, (sp, 0); \
  addi sp, 8

#undef  UNDOARGS2_6
#define UNDOARGS2_6 \
  ldw  r4, (sp, 0); \
  ldw  r5, (sp, 4); \
  addi sp, 8

#endif  /* __CSKYABIV2__ */

#endif /* __ASSEMBLER__ */
#endif /* _LINUX_CSKY_SYSDEP_H */