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