1 | /* Copyright (C) 1997-2024 Free Software Foundation, Inc. |
2 | This file is part of the GNU C Library. |
3 | |
4 | The GNU C Library is free software; you can redistribute it and/or |
5 | modify it under the terms of the GNU Lesser General Public |
6 | License as published by the Free Software Foundation; either |
7 | version 2.1 of the License, or (at your option) any later version. |
8 | |
9 | The GNU C Library is distributed in the hope that it will be useful, |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
12 | Lesser General Public License for more details. |
13 | |
14 | You should have received a copy of the GNU Lesser General Public |
15 | License along with the GNU C Library. If not, see |
16 | <https://www.gnu.org/licenses/>. */ |
17 | |
18 | #ifndef _SYS_ASM_H |
19 | #define _SYS_ASM_H |
20 | |
21 | #include <sgidefs.h> |
22 | |
23 | #ifndef CAT |
24 | # define __CAT(str1,str2) str1##str2 |
25 | # define CAT(str1,str2) __CAT(str1,str2) |
26 | #endif |
27 | |
28 | /* Redefined as nonempty in the internal header. */ |
29 | #define __mips_cfi_startproc /* Empty. */ |
30 | #define __mips_cfi_endproc /* Empty. */ |
31 | |
32 | /* |
33 | * Macros to handle different pointer/register sizes for 32/64-bit code |
34 | * |
35 | * 64 bit address space isn't used yet, so we may use the R3000 32 bit |
36 | * defines for now. |
37 | */ |
38 | #if _MIPS_SIM == _ABIO32 || _MIPS_SIM == _ABIN32 |
39 | # define PTR .word |
40 | # define PTRSIZE 4 |
41 | # define PTRLOG 2 |
42 | #elif _MIPS_SIM == _ABI64 |
43 | # define PTR .dword |
44 | # define PTRSIZE 8 |
45 | # define PTRLOG 3 |
46 | #endif |
47 | |
48 | /* |
49 | * PIC specific declarations |
50 | */ |
51 | #if _MIPS_SIM == _ABIO32 |
52 | # ifdef __PIC__ |
53 | # define CPRESTORE(register) \ |
54 | .cprestore register |
55 | # define CPLOAD(register) \ |
56 | .cpload register |
57 | # else |
58 | # define CPRESTORE(register) |
59 | # define CPLOAD(register) |
60 | # endif |
61 | |
62 | # define CPADD(register) \ |
63 | .cpadd register |
64 | |
65 | /* |
66 | * Set gp when at 1st instruction |
67 | */ |
68 | # define SETUP_GP \ |
69 | .set noreorder; \ |
70 | .cpload $25; \ |
71 | .set reorder |
72 | /* Set gp when not at 1st instruction */ |
73 | # define SETUP_GPX(r) \ |
74 | .set noreorder; \ |
75 | move r, $31; /* Save old ra. */ \ |
76 | bal 10f; /* Find addr of cpload. */ \ |
77 | nop; \ |
78 | 10: \ |
79 | .cpload $31; \ |
80 | move $31, r; \ |
81 | .set reorder |
82 | # define SETUP_GPX_L(r, l) \ |
83 | .set noreorder; \ |
84 | move r, $31; /* Save old ra. */ \ |
85 | bal l; /* Find addr of cpload. */ \ |
86 | nop; \ |
87 | l: \ |
88 | .cpload $31; \ |
89 | move $31, r; \ |
90 | .set reorder |
91 | # define SAVE_GP(x) \ |
92 | .cprestore x /* Save gp trigger t9/jalr conversion. */ |
93 | # define SETUP_GP64(a, b) |
94 | # define SETUP_GPX64(a, b) |
95 | # define SETUP_GPX64_L(cp_reg, ra_save, l) |
96 | # define RESTORE_GP64 |
97 | # define USE_ALT_CP(a) |
98 | #else /* _MIPS_SIM == _ABI64 || _MIPS_SIM == _ABIN32 */ |
99 | /* |
100 | * For callee-saved gp calling convention: |
101 | */ |
102 | # define SETUP_GP |
103 | # define SETUP_GPX(r) |
104 | # define SETUP_GPX_L(r, l) |
105 | # define SAVE_GP(x) |
106 | |
107 | # define SETUP_GP64(gpoffset, proc) \ |
108 | .cpsetup $25, gpoffset, proc |
109 | # define SETUP_GPX64(cp_reg, ra_save) \ |
110 | move ra_save, $31; /* Save old ra. */ \ |
111 | .set noreorder; \ |
112 | bal 10f; /* Find addr of .cpsetup. */ \ |
113 | nop; \ |
114 | 10: \ |
115 | .set reorder; \ |
116 | .cpsetup $31, cp_reg, 10b; \ |
117 | move $31, ra_save |
118 | # define SETUP_GPX64_L(cp_reg, ra_save, l) \ |
119 | move ra_save, $31; /* Save old ra. */ \ |
120 | .set noreorder; \ |
121 | bal l; /* Find addr of .cpsetup. */ \ |
122 | nop; \ |
123 | l: \ |
124 | .set reorder; \ |
125 | .cpsetup $31, cp_reg, l; \ |
126 | move $31, ra_save |
127 | # define RESTORE_GP64 \ |
128 | .cpreturn |
129 | /* Use alternate register for context pointer. */ |
130 | # define USE_ALT_CP(reg) \ |
131 | .cplocal reg |
132 | #endif /* _MIPS_SIM != _ABIO32 */ |
133 | |
134 | /* |
135 | * Stack Frame Definitions |
136 | */ |
137 | #if _MIPS_SIM == _ABIO32 |
138 | # define NARGSAVE 4 /* Space for 4 argument registers must be allocated. */ |
139 | #endif |
140 | #if _MIPS_SIM == _ABI64 || _MIPS_SIM == _ABIN32 |
141 | # define NARGSAVE 0 /* No caller responsibilities. */ |
142 | #endif |
143 | |
144 | |
145 | /* |
146 | * LEAF - declare leaf routine |
147 | */ |
148 | #define LEAF(symbol) \ |
149 | .globl symbol; \ |
150 | .align 2; \ |
151 | .type symbol,@function; \ |
152 | .ent symbol,0; \ |
153 | symbol: .frame sp,0,ra; \ |
154 | __mips_cfi_startproc |
155 | |
156 | /* |
157 | * NESTED - declare nested routine entry point |
158 | */ |
159 | #define NESTED(symbol, framesize, rpc) \ |
160 | .globl symbol; \ |
161 | .align 2; \ |
162 | .type symbol,@function; \ |
163 | .ent symbol,0; \ |
164 | symbol: .frame sp, framesize, rpc; \ |
165 | __mips_cfi_startproc |
166 | |
167 | /* |
168 | * END - mark end of function |
169 | */ |
170 | #ifndef END |
171 | # define END(function) \ |
172 | __mips_cfi_endproc; \ |
173 | .end function; \ |
174 | .size function,.-function |
175 | #endif |
176 | |
177 | /* |
178 | * EXPORT - export definition of symbol |
179 | */ |
180 | #define EXPORT(symbol) \ |
181 | .globl symbol; \ |
182 | symbol: __mips_cfi_startproc |
183 | |
184 | /* |
185 | * ABS - export absolute symbol |
186 | */ |
187 | #define ABS(symbol,value) \ |
188 | .globl symbol; \ |
189 | symbol = value |
190 | |
191 | #define PANIC(msg) \ |
192 | .set push; \ |
193 | .set reorder; \ |
194 | la a0,8f; \ |
195 | jal panic; \ |
196 | 9: b 9b; \ |
197 | .set pop; \ |
198 | TEXT(msg) |
199 | |
200 | /* |
201 | * Print formatted string |
202 | */ |
203 | #define PRINT(string) \ |
204 | .set push; \ |
205 | .set reorder; \ |
206 | la a0,8f; \ |
207 | jal printk; \ |
208 | .set pop; \ |
209 | TEXT(string) |
210 | |
211 | #define TEXT(msg) \ |
212 | .data; \ |
213 | 8: .asciiz msg; \ |
214 | .previous; |
215 | |
216 | /* |
217 | * Build text tables |
218 | */ |
219 | #define TTABLE(string) \ |
220 | .text; \ |
221 | .word 1f; \ |
222 | .previous; \ |
223 | .data; \ |
224 | 1: .asciz string; \ |
225 | .previous |
226 | |
227 | /* |
228 | * MIPS IV pref instruction. |
229 | * Use with .set noreorder only! |
230 | * |
231 | * MIPS IV implementations are free to treat this as a nop. The R5000 |
232 | * is one of them. So we should have an option not to use this instruction. |
233 | */ |
234 | #if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) \ |
235 | || (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) |
236 | # define PREF(hint,addr) \ |
237 | pref hint,addr |
238 | # define PREFX(hint,addr) \ |
239 | prefx hint,addr |
240 | #else |
241 | # define PREF(hint,addr) |
242 | # define PREFX(hint,addr) |
243 | #endif |
244 | |
245 | /* |
246 | * MIPS ISA IV/V movn/movz instructions and equivalents for older CPUs. |
247 | */ |
248 | #if _MIPS_ISA == _MIPS_ISA_MIPS1 |
249 | # define MOVN(rd,rs,rt) \ |
250 | .set push; \ |
251 | .set reorder; \ |
252 | beqz rt,9f; \ |
253 | move rd,rs; \ |
254 | .set pop; \ |
255 | 9: |
256 | # define MOVZ(rd,rs,rt) \ |
257 | .set push; \ |
258 | .set reorder; \ |
259 | bnez rt,9f; \ |
260 | move rd,rt; \ |
261 | .set pop; \ |
262 | 9: |
263 | #endif /* _MIPS_ISA == _MIPS_ISA_MIPS1 */ |
264 | #if (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) |
265 | # define MOVN(rd,rs,rt) \ |
266 | .set push; \ |
267 | .set noreorder; \ |
268 | bnezl rt,9f; \ |
269 | move rd,rs; \ |
270 | .set pop; \ |
271 | 9: |
272 | # define MOVZ(rd,rs,rt) \ |
273 | .set push; \ |
274 | .set noreorder; \ |
275 | beqzl rt,9f; \ |
276 | movz rd,rs; \ |
277 | .set pop; \ |
278 | 9: |
279 | #endif /* (_MIPS_ISA == _MIPS_ISA_MIPS2) || (_MIPS_ISA == _MIPS_ISA_MIPS3) */ |
280 | #if (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) \ |
281 | || (_MIPS_ISA == _MIPS_ISA_MIPS32) || (_MIPS_ISA == _MIPS_ISA_MIPS64) |
282 | # define MOVN(rd,rs,rt) \ |
283 | movn rd,rs,rt |
284 | # define MOVZ(rd,rs,rt) \ |
285 | movz rd,rs,rt |
286 | #endif /* (_MIPS_ISA == _MIPS_ISA_MIPS4) || (_MIPS_ISA == _MIPS_ISA_MIPS5) */ |
287 | |
288 | /* |
289 | * Stack alignment |
290 | */ |
291 | #if _MIPS_SIM == _ABI64 || _MIPS_SIM == _ABIN32 |
292 | # define ALSZ 15 |
293 | # define ALMASK ~15 |
294 | #else |
295 | # define ALSZ 7 |
296 | # define ALMASK ~7 |
297 | #endif |
298 | |
299 | /* |
300 | * Size of a register |
301 | */ |
302 | #if _MIPS_SIM == _ABI64 || _MIPS_SIM == _ABIN32 |
303 | # define SZREG 8 |
304 | #else |
305 | # define SZREG 4 |
306 | #endif |
307 | |
308 | /* |
309 | * Use the following macros in assemblercode to load/store registers, |
310 | * pointers etc. |
311 | */ |
312 | #if (SZREG == 4) |
313 | # define REG_S sw |
314 | # define REG_L lw |
315 | #else |
316 | # define REG_S sd |
317 | # define REG_L ld |
318 | #endif |
319 | |
320 | /* |
321 | * How to add/sub/load/store/shift C int variables. |
322 | */ |
323 | #if (_MIPS_SZINT == 32) |
324 | # define INT_ADD add |
325 | # define INT_ADDI addi |
326 | # define INT_ADDU addu |
327 | # define INT_ADDIU addiu |
328 | # define INT_SUB sub |
329 | # define INT_SUBI subi |
330 | # define INT_SUBU subu |
331 | # define INT_SUBIU subu |
332 | # define INT_L lw |
333 | # define INT_S sw |
334 | #endif |
335 | |
336 | #if (_MIPS_SZINT == 64) |
337 | # define INT_ADD dadd |
338 | # define INT_ADDI daddi |
339 | # define INT_ADDU daddu |
340 | # define INT_ADDIU daddiu |
341 | # define INT_SUB dsub |
342 | # define INT_SUBI dsubi |
343 | # define INT_SUBU dsubu |
344 | # define INT_SUBIU dsubu |
345 | # define INT_L ld |
346 | # define INT_S sd |
347 | #endif |
348 | |
349 | /* |
350 | * How to add/sub/load/store/shift C long variables. |
351 | */ |
352 | #if (_MIPS_SZLONG == 32) |
353 | # define LONG_ADD add |
354 | # define LONG_ADDI addi |
355 | # define LONG_ADDU addu |
356 | # define LONG_ADDIU addiu |
357 | # define LONG_SUB sub |
358 | # define LONG_SUBI subi |
359 | # define LONG_SUBU subu |
360 | # define LONG_SUBIU subu |
361 | # define LONG_L lw |
362 | # define LONG_S sw |
363 | # define LONG_SLL sll |
364 | # define LONG_SLLV sllv |
365 | # define LONG_SRL srl |
366 | # define LONG_SRLV srlv |
367 | # define LONG_SRA sra |
368 | # define LONG_SRAV srav |
369 | #endif |
370 | |
371 | #if (_MIPS_SZLONG == 64) |
372 | # define LONG_ADD dadd |
373 | # define LONG_ADDI daddi |
374 | # define LONG_ADDU daddu |
375 | # define LONG_ADDIU daddiu |
376 | # define LONG_SUB dsub |
377 | # define LONG_SUBI dsubi |
378 | # define LONG_SUBU dsubu |
379 | # define LONG_SUBIU dsubu |
380 | # define LONG_L ld |
381 | # define LONG_S sd |
382 | # define LONG_SLL dsll |
383 | # define LONG_SLLV dsllv |
384 | # define LONG_SRL dsrl |
385 | # define LONG_SRLV dsrlv |
386 | # define LONG_SRA dsra |
387 | # define LONG_SRAV dsrav |
388 | #endif |
389 | |
390 | /* |
391 | * How to add/sub/load/store/shift pointers. |
392 | */ |
393 | #if (_MIPS_SIM == _ABIO32 && _MIPS_SZPTR == 32) |
394 | # define PTR_ADD add |
395 | # define PTR_ADDI addi |
396 | # define PTR_ADDU addu |
397 | # define PTR_ADDIU addiu |
398 | # define PTR_SUB sub |
399 | # define PTR_SUBI subi |
400 | # define PTR_SUBU subu |
401 | # define PTR_SUBIU subu |
402 | # define PTR_L lw |
403 | # define PTR_LA la |
404 | # define PTR_S sw |
405 | # define PTR_SLL sll |
406 | # define PTR_SLLV sllv |
407 | # define PTR_SRL srl |
408 | # define PTR_SRLV srlv |
409 | # define PTR_SRA sra |
410 | # define PTR_SRAV srav |
411 | |
412 | # define PTR_SCALESHIFT 2 |
413 | #endif |
414 | |
415 | #if _MIPS_SIM == _ABIN32 |
416 | # define PTR_ADD add |
417 | # define PTR_ADDI addi |
418 | # define PTR_SUB sub |
419 | # define PTR_SUBI subi |
420 | #if !defined __mips_isa_rev || __mips_isa_rev < 6 |
421 | # define PTR_ADDU add /* no u */ |
422 | # define PTR_ADDIU addi /* no u */ |
423 | # define PTR_SUBU sub /* no u */ |
424 | # define PTR_SUBIU sub /* no u */ |
425 | #else |
426 | # define PTR_ADDU addu |
427 | # define PTR_ADDIU addiu |
428 | # define PTR_SUBU subu |
429 | # define PTR_SUBIU subu |
430 | #endif |
431 | # define PTR_L lw |
432 | # define PTR_LA la |
433 | # define PTR_S sw |
434 | # define PTR_SLL sll |
435 | # define PTR_SLLV sllv |
436 | # define PTR_SRL srl |
437 | # define PTR_SRLV srlv |
438 | # define PTR_SRA sra |
439 | # define PTR_SRAV srav |
440 | |
441 | # define PTR_SCALESHIFT 2 |
442 | #endif |
443 | |
444 | #if (_MIPS_SIM == _ABIO32 && _MIPS_SZPTR == 64 /* o64??? */) \ |
445 | || _MIPS_SIM == _ABI64 |
446 | # define PTR_ADD dadd |
447 | # define PTR_ADDI daddi |
448 | # define PTR_ADDU daddu |
449 | # define PTR_ADDIU daddiu |
450 | # define PTR_SUB dsub |
451 | # define PTR_SUBI dsubi |
452 | # define PTR_SUBU dsubu |
453 | # define PTR_SUBIU dsubu |
454 | # define PTR_L ld |
455 | # define PTR_LA dla |
456 | # define PTR_S sd |
457 | # define PTR_SLL dsll |
458 | # define PTR_SLLV dsllv |
459 | # define PTR_SRL dsrl |
460 | # define PTR_SRLV dsrlv |
461 | # define PTR_SRA dsra |
462 | # define PTR_SRAV dsrav |
463 | |
464 | # define PTR_SCALESHIFT 3 |
465 | #endif |
466 | |
467 | /* |
468 | * Some cp0 registers were extended to 64bit for MIPS III. |
469 | */ |
470 | #if (_MIPS_ISA == _MIPS_ISA_MIPS1) || (_MIPS_ISA == _MIPS_ISA_MIPS2) \ |
471 | || (_MIPS_ISA == _MIPS_ISA_MIPS32) |
472 | # define MFC0 mfc0 |
473 | # define MTC0 mtc0 |
474 | #endif |
475 | #if (_MIPS_ISA == _MIPS_ISA_MIPS3) || (_MIPS_ISA == _MIPS_ISA_MIPS4) \ |
476 | || (_MIPS_ISA == _MIPS_ISA_MIPS5) || (_MIPS_ISA == _MIPS_ISA_MIPS64) |
477 | # define MFC0 dmfc0 |
478 | # define MTC0 dmtc0 |
479 | #endif |
480 | |
481 | /* The MIPS architectures do not have a uniform memory model. Particular |
482 | platforms may provide additional guarantees - for instance, the R4000 |
483 | LL and SC instructions implicitly perform a SYNC, and the 4K promises |
484 | strong ordering. |
485 | |
486 | However, in the absence of those guarantees, we must assume weak ordering |
487 | and SYNC explicitly where necessary. |
488 | |
489 | Some obsolete MIPS processors may not support the SYNC instruction. This |
490 | applies to "true" MIPS I processors; most of the processors which compile |
491 | using MIPS I implement parts of MIPS II. */ |
492 | |
493 | #ifndef MIPS_SYNC |
494 | # define MIPS_SYNC sync |
495 | #endif |
496 | |
497 | #endif /* sys/asm.h */ |
498 | |