1 /* Copyright (C) 1997-2021 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 formated 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