1/* Copyright (C) 1997-2026 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; \
7810: \
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; \
87l: \
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; \
11410: \
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; \
123l: \
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; \
153symbol: .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; \
164symbol: .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; \
182symbol: __mips_cfi_startproc
183
184/*
185 * ABS - export absolute symbol
186 */
187#define ABS(symbol,value) \
188 .globl symbol; \
189symbol = value
190
191#define PANIC(msg) \
192 .set push; \
193 .set reorder; \
194 la a0,8f; \
195 jal panic; \
1969: 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; \
2138: .asciiz msg; \
214 .previous;
215
216/*
217 * Build text tables
218 */
219#define TTABLE(string) \
220 .text; \
221 .word 1f; \
222 .previous; \
223 .data; \
2241: .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; \
2559:
256# define MOVZ(rd,rs,rt) \
257 .set push; \
258 .set reorder; \
259 bnez rt,9f; \
260 move rd,rt; \
261 .set pop; \
2629:
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; \
2719:
272# define MOVZ(rd,rs,rt) \
273 .set push; \
274 .set noreorder; \
275 beqzl rt,9f; \
276 movz rd,rs; \
277 .set pop; \
2789:
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#endif /* sys/asm.h */