1/* Save current context and jump to a new context. 2 Copyright (C) 2005-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19/* This is the common implementation of setcontext for powerpc32. 20 It not complete in itself should be included in to a framework that 21 defines: 22 __CONTEXT_FUNC_NAME 23 and if appropriate: 24 __CONTEXT_ENABLE_FPRS 25 __CONTEXT_ENABLE_VRS 26 Any architecture that implements the Vector unit is assumed to also 27 implement the floating unit. */ 28 29/* Stack frame offsets. */ 30#define _FRAME_BACKCHAIN 0 31#define _FRAME_LR_SAVE 4 32#define _FRAME_PARM_SAVE1 8 33#define _FRAME_PARM_SAVE2 12 34#define _FRAME_PARM_SAVE3 16 35#define _FRAME_PARM_SAVE4 20 36 37#ifdef __CONTEXT_ENABLE_VRS 38 .machine "altivec" 39#endif 40ENTRY(__CONTEXT_FUNC_NAME) 41 stwu r1,-16(r1) 42 cfi_adjust_cfa_offset (16) 43/* Insure that the _UC_REGS start on a quadword boundary. */ 44 stw r3,_FRAME_PARM_SAVE1(r1) 45 addi r3,r3,_UC_REG_SPACE+12 46 stw r4,_FRAME_PARM_SAVE2(r1) /* new context pointer */ 47 clrrwi r3,r3,4 48 49/* Save the general purpose registers */ 50 stw r0,_UC_GREGS+(PT_R0*4)(r3) 51 mflr r0 52 stw r2,_UC_GREGS+(PT_R2*4)(r3) 53 stw r4,_UC_GREGS+(PT_R4*4)(r3) 54/* Set the callers LR_SAVE, and the ucontext LR and NIP to the callers 55 return address. */ 56 stw r0,_UC_GREGS+(PT_LNK*4)(r3) 57 stw r0,_UC_GREGS+(PT_NIP*4)(r3) 58 stw r0,_FRAME_LR_SAVE+16(r1) 59 cfi_offset (lr, _FRAME_LR_SAVE) 60 stw r5,_UC_GREGS+(PT_R5*4)(r3) 61 stw r6,_UC_GREGS+(PT_R6*4)(r3) 62 stw r7,_UC_GREGS+(PT_R7*4)(r3) 63 stw r8,_UC_GREGS+(PT_R8*4)(r3) 64 stw r9,_UC_GREGS+(PT_R9*4)(r3) 65 stw r10,_UC_GREGS+(PT_R10*4)(r3) 66 stw r11,_UC_GREGS+(PT_R11*4)(r3) 67 stw r12,_UC_GREGS+(PT_R12*4)(r3) 68 stw r13,_UC_GREGS+(PT_R13*4)(r3) 69 stw r14,_UC_GREGS+(PT_R14*4)(r3) 70 stw r15,_UC_GREGS+(PT_R15*4)(r3) 71 stw r16,_UC_GREGS+(PT_R16*4)(r3) 72 stw r17,_UC_GREGS+(PT_R17*4)(r3) 73 stw r18,_UC_GREGS+(PT_R18*4)(r3) 74 stw r19,_UC_GREGS+(PT_R19*4)(r3) 75 stw r20,_UC_GREGS+(PT_R20*4)(r3) 76 stw r21,_UC_GREGS+(PT_R21*4)(r3) 77 stw r22,_UC_GREGS+(PT_R22*4)(r3) 78 stw r23,_UC_GREGS+(PT_R23*4)(r3) 79 stw r24,_UC_GREGS+(PT_R24*4)(r3) 80 stw r25,_UC_GREGS+(PT_R25*4)(r3) 81 stw r26,_UC_GREGS+(PT_R26*4)(r3) 82 stw r27,_UC_GREGS+(PT_R27*4)(r3) 83 stw r28,_UC_GREGS+(PT_R28*4)(r3) 84 stw r29,_UC_GREGS+(PT_R29*4)(r3) 85 stw r30,_UC_GREGS+(PT_R30*4)(r3) 86 stw r31,_UC_GREGS+(PT_R31*4)(r3) 87 88/* Save the value of R1. We had to push the stack before we 89 had the address of uc_reg_space. So compute the address of 90 the callers stack pointer and save it as R1. */ 91 addi r8,r1,16 92 li r0,0 93/* Save the count, exception and condition registers. */ 94 mfctr r11 95 mfxer r10 96 mfcr r9 97 stw r8,_UC_GREGS+(PT_R1*4)(r3) 98 stw r11,_UC_GREGS+(PT_CTR*4)(r3) 99 stw r10,_UC_GREGS+(PT_XER*4)(r3) 100 stw r9,_UC_GREGS+(PT_CCR*4)(r3) 101/* Set the return value of getcontext to "success". R3 is the only 102 register whose value is not preserved in the saved context. */ 103 stw r0,_UC_GREGS+(PT_R3*4)(r3) 104 105 /* Zero fill fields that can't be set in user state. */ 106 stw r0,_UC_GREGS+(PT_MSR*4)(r3) 107 stw r0,_UC_GREGS+(PT_MQ*4)(r3) 108 109#ifdef __CONTEXT_ENABLE_FPRS 110 /* Save the floating-point registers */ 111 stfd fp0,_UC_FREGS+(0*8)(r3) 112 stfd fp1,_UC_FREGS+(1*8)(r3) 113 stfd fp2,_UC_FREGS+(2*8)(r3) 114 stfd fp3,_UC_FREGS+(3*8)(r3) 115 stfd fp4,_UC_FREGS+(4*8)(r3) 116 stfd fp5,_UC_FREGS+(5*8)(r3) 117 stfd fp6,_UC_FREGS+(6*8)(r3) 118 stfd fp7,_UC_FREGS+(7*8)(r3) 119 stfd fp8,_UC_FREGS+(8*8)(r3) 120 stfd fp9,_UC_FREGS+(9*8)(r3) 121 stfd fp10,_UC_FREGS+(10*8)(r3) 122 stfd fp11,_UC_FREGS+(11*8)(r3) 123 stfd fp12,_UC_FREGS+(12*8)(r3) 124 stfd fp13,_UC_FREGS+(13*8)(r3) 125 stfd fp14,_UC_FREGS+(14*8)(r3) 126 stfd fp15,_UC_FREGS+(15*8)(r3) 127 stfd fp16,_UC_FREGS+(16*8)(r3) 128 stfd fp17,_UC_FREGS+(17*8)(r3) 129 stfd fp18,_UC_FREGS+(18*8)(r3) 130 stfd fp19,_UC_FREGS+(19*8)(r3) 131 stfd fp20,_UC_FREGS+(20*8)(r3) 132 stfd fp21,_UC_FREGS+(21*8)(r3) 133 stfd fp22,_UC_FREGS+(22*8)(r3) 134 stfd fp23,_UC_FREGS+(23*8)(r3) 135 stfd fp24,_UC_FREGS+(24*8)(r3) 136 stfd fp25,_UC_FREGS+(25*8)(r3) 137 stfd fp26,_UC_FREGS+(26*8)(r3) 138 stfd fp27,_UC_FREGS+(27*8)(r3) 139 stfd fp28,_UC_FREGS+(28*8)(r3) 140 stfd fp29,_UC_FREGS+(29*8)(r3) 141 mffs fp0 142 stfd fp30,_UC_FREGS+(30*8)(r3) 143 stfd fp31,_UC_FREGS+(31*8)(r3) 144 stfd fp0,_UC_FREGS+(32*8)(r3) 145 146# ifdef PIC 147 mflr r8 148# define got_label GENERATE_GOT_LABEL (__CONTEXT_FUNC_NAME) 149 SETUP_GOT_ACCESS(r7,got_label) 150 addis r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@ha 151 addi r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@l 152# ifdef SHARED 153 lwz r7,_rtld_global_ro@got(r7) 154 mtlr r8 155 lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7) 156# else 157 lwz r7,_dl_hwcap@got(r7) 158 mtlr r8 159 lwz r7,LOWORD(r7) 160# endif 161# else 162 lis r7,(_dl_hwcap+LOWORD)@ha 163 lwz r7,(_dl_hwcap+LOWORD)@l(r7) 164# endif 165 166# ifdef __CONTEXT_ENABLE_VRS 167 andis. r6,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16) 168 169 la r10,(_UC_VREGS)(r3) 170 la r9,(_UC_VREGS+16)(r3) 171 172/* beq L(no_vec)*/ 173 beq 2f 174/* address of the combined VSCR/VSAVE quadword. */ 175 la r8,(_UC_VREGS+512)(r3) 176 177/* Save the vector registers */ 178 stvx v0,0,r10 179 stvx v1,0,r9 180 addi r10,r10,32 181 addi r9,r9,32 182/* We need to get the Vector Status and Control Register early to avoid 183 store order problems later with the VSAVE register that shares the 184 same quadword. */ 185 mfvscr v0 186 187 stvx v2,0,r10 188 stvx v3,0,r9 189 addi r10,r10,32 190 addi r9,r9,32 191 192 stvx v0,0,r8 193 194 stvx v4,0,r10 195 stvx v5,0,r9 196 addi r10,r10,32 197 addi r9,r9,32 198 199 stvx v6,0,r10 200 stvx v7,0,r9 201 addi r10,r10,32 202 addi r9,r9,32 203 204 stvx v8,0,r10 205 stvx v9,0,r9 206 addi r10,r10,32 207 addi r9,r9,32 208 209 stvx v10,0,r10 210 stvx v11,0,r9 211 addi r10,r10,32 212 addi r9,r9,32 213 214 stvx v12,0,r10 215 stvx v13,0,r9 216 addi r10,r10,32 217 addi r9,r9,32 218 219 stvx v14,0,r10 220 stvx v15,0,r9 221 addi r10,r10,32 222 addi r9,r9,32 223 224 stvx v16,0,r10 225 stvx v17,0,r9 226 addi r10,r10,32 227 addi r9,r9,32 228 229 stvx v18,0,r10 230 stvx v19,0,r9 231 addi r10,r10,32 232 addi r9,r9,32 233 234 stvx v20,0,r10 235 stvx v21,0,r9 236 addi r10,r10,32 237 addi r9,r9,32 238 239 stvx v22,0,r10 240 stvx v23,0,r9 241 addi r10,r10,32 242 addi r9,r9,32 243 244 stvx v24,0,r10 245 stvx v25,0,r9 246 addi r10,r10,32 247 addi r9,r9,32 248 249 stvx v26,0,r10 250 stvx v27,0,r9 251 addi r10,r10,32 252 addi r9,r9,32 253 254 stvx v28,0,r10 255 stvx v29,0,r9 256 addi r10,r10,32 257 addi r9,r9,32 258 259 mfvscr v0 260 stvx v30,0,r10 261 stvx v31,0,r9 262 stw r0,0(r8) 263 2642: /*L(no_vec):*/ 265# endif /* __CONTEXT_ENABLE_VRS */ 266#endif /* __CONTEXT_ENABLE_FPRS */ 267 268/* Restore ucontext (parm1) from stack. */ 269 lwz r12,_FRAME_PARM_SAVE1(r1) 270 lwz r4,_FRAME_PARM_SAVE2(r1) 271 addi r4,r4,_UC_SIGMASK 272 stw r3,_UC_REGS_PTR(r12) 273 addi r5,r12,_UC_SIGMASK 274 li r3,SIG_SETMASK 275 bl __sigprocmask@local 276 cmpwi r3,0 277 bne 3f /* L(error_exit) */ 278 279 lwz r4,_FRAME_PARM_SAVE2(r1) 280 lwz r31,_UC_REGS_PTR(r4) 281 282#ifdef __CONTEXT_ENABLE_FPRS 283# ifdef __CONTEXT_ENABLE_VRS 284 285# ifdef PIC 286 mflr r8 287 SETUP_GOT_ACCESS(r7,got_label) 288 addis r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@ha 289 addi r7,r7,_GLOBAL_OFFSET_TABLE_-got_label@l 290 mtlr r8 291# ifdef SHARED 292 lwz r7,_rtld_global_ro@got(r7) 293 lwz r7,RTLD_GLOBAL_RO_DL_HWCAP_OFFSET+LOWORD(r7) 294# else 295 lwz r7,_dl_hwcap@got(r7) 296 lwz r7,LOWORD(r7) 297# endif 298# else 299 lis r7,(_dl_hwcap+LOWORD)@ha 300 lwz r7,(_dl_hwcap+LOWORD)@l(r7) 301# endif 302 andis. r7,r7,(PPC_FEATURE_HAS_ALTIVEC >> 16) 303 la r10,(_UC_VREGS)(r31) 304 beq 6f /* L(has_no_vec) */ 305 306 lwz r0,(32*16)(r10) 307 li r9,(32*16) 308 cmpwi r0,0 309 mtspr VRSAVE,r0 310 beq 6f /* L(has_no_vec) */ 311 312 lvx v19,r9,r10 313 la r9,(16)(r10) 314 315 lvx v0,0,r10 316 lvx v1,0,r9 317 addi r10,r10,32 318 addi r9,r9,32 319 320 mtvscr v19 321 lvx v2,0,r10 322 lvx v3,0,r9 323 addi r10,r10,32 324 addi r9,r9,32 325 326 lvx v4,0,r10 327 lvx v5,0,r9 328 addi r10,r10,32 329 addi r9,r9,32 330 331 lvx v6,0,r10 332 lvx v7,0,r9 333 addi r10,r10,32 334 addi r9,r9,32 335 336 lvx v8,0,r10 337 lvx v9,0,r9 338 addi r10,r10,32 339 addi r9,r9,32 340 341 lvx v10,0,r10 342 lvx v11,0,r9 343 addi r10,r10,32 344 addi r9,r9,32 345 346 lvx v12,0,r10 347 lvx v13,0,r9 348 addi r10,r10,32 349 addi r9,r9,32 350 351 lvx v14,0,r10 352 lvx v15,0,r9 353 addi r10,r10,32 354 addi r9,r9,32 355 356 lvx v16,0,r10 357 lvx v17,0,r9 358 addi r10,r10,32 359 addi r9,r9,32 360 361 lvx v18,0,r10 362 lvx v19,0,r9 363 addi r10,r10,32 364 addi r9,r9,32 365 366 lvx v20,0,r10 367 lvx v21,0,r9 368 addi r10,r10,32 369 addi r9,r9,32 370 371 lvx v22,0,r10 372 lvx v23,0,r9 373 addi r10,r10,32 374 addi r9,r9,32 375 376 lvx v24,0,r10 377 lvx v25,0,r9 378 addi r10,r10,32 379 addi r9,r9,32 380 381 lvx v26,0,r10 382 lvx v27,0,r9 383 addi r10,r10,32 384 addi r9,r9,32 385 386 lvx v28,0,r10 387 lvx v29,0,r9 388 addi r10,r10,32 389 addi r9,r9,32 390 391 lvx v30,0,r10 392 lvx v31,0,r9 393 addi r10,r10,32 394 addi r9,r9,32 395 396 lvx v10,0,r10 397 lvx v11,0,r9 398 3996: /* L(has_no_vec): */ 400# endif /* __CONTEXT_ENABLE_VRS */ 401 /* Restore the floating-point registers */ 402 lfd fp31,_UC_FREGS+(32*8)(r31) 403 lfd fp0,_UC_FREGS+(0*8)(r31) 404# ifdef _ARCH_PWR6 405 /* Use the extended four-operand version of the mtfsf insn. */ 406 mtfsf 0xff,fp31,1,0 407# else 408 .machine push 409 .machine "power6" 410 /* Availability of DFP indicates a 64-bit FPSCR. */ 411 andi. r6,r7,PPC_FEATURE_HAS_DFP 412 beq 7f 413 /* Use the extended four-operand version of the mtfsf insn. */ 414 mtfsf 0xff,fp31,1,0 415 b 8f 416 /* Continue to operate on the FPSCR as if it were 32-bits. */ 4177: mtfsf 0xff,fp31 4188: .machine pop 419#endif /* _ARCH_PWR6 */ 420 lfd fp1,_UC_FREGS+(1*8)(r31) 421 lfd fp2,_UC_FREGS+(2*8)(r31) 422 lfd fp3,_UC_FREGS+(3*8)(r31) 423 lfd fp4,_UC_FREGS+(4*8)(r31) 424 lfd fp5,_UC_FREGS+(5*8)(r31) 425 lfd fp6,_UC_FREGS+(6*8)(r31) 426 lfd fp7,_UC_FREGS+(7*8)(r31) 427 lfd fp8,_UC_FREGS+(8*8)(r31) 428 lfd fp9,_UC_FREGS+(9*8)(r31) 429 lfd fp10,_UC_FREGS+(10*8)(r31) 430 lfd fp11,_UC_FREGS+(11*8)(r31) 431 lfd fp12,_UC_FREGS+(12*8)(r31) 432 lfd fp13,_UC_FREGS+(13*8)(r31) 433 lfd fp14,_UC_FREGS+(14*8)(r31) 434 lfd fp15,_UC_FREGS+(15*8)(r31) 435 lfd fp16,_UC_FREGS+(16*8)(r31) 436 lfd fp17,_UC_FREGS+(17*8)(r31) 437 lfd fp18,_UC_FREGS+(18*8)(r31) 438 lfd fp19,_UC_FREGS+(19*8)(r31) 439 lfd fp20,_UC_FREGS+(20*8)(r31) 440 lfd fp21,_UC_FREGS+(21*8)(r31) 441 lfd fp22,_UC_FREGS+(22*8)(r31) 442 lfd fp23,_UC_FREGS+(23*8)(r31) 443 lfd fp24,_UC_FREGS+(24*8)(r31) 444 lfd fp25,_UC_FREGS+(25*8)(r31) 445 lfd fp26,_UC_FREGS+(26*8)(r31) 446 lfd fp27,_UC_FREGS+(27*8)(r31) 447 lfd fp28,_UC_FREGS+(28*8)(r31) 448 lfd fp29,_UC_FREGS+(29*8)(r31) 449 lfd fp30,_UC_FREGS+(30*8)(r31) 450 lfd fp31,_UC_FREGS+(31*8)(r31) 451#endif /* __CONTEXT_ENABLE_FPRS */ 452 453 /* Restore LR and CCR, and set CTR to the NIP value */ 454 lwz r3,_UC_GREGS+(PT_LNK*4)(r31) 455 lwz r4,_UC_GREGS+(PT_NIP*4)(r31) 456 lwz r5,_UC_GREGS+(PT_CCR*4)(r31) 457 mtlr r3 458 mtctr r4 459 mtcr r5 460 461 /* Restore the general registers */ 462 lwz r3,_UC_GREGS+(PT_R3*4)(r31) 463 lwz r4,_UC_GREGS+(PT_R4*4)(r31) 464 lwz r5,_UC_GREGS+(PT_R5*4)(r31) 465 lwz r6,_UC_GREGS+(PT_R6*4)(r31) 466 lwz r7,_UC_GREGS+(PT_R7*4)(r31) 467 lwz r8,_UC_GREGS+(PT_R8*4)(r31) 468 lwz r9,_UC_GREGS+(PT_R9*4)(r31) 469 lwz r10,_UC_GREGS+(PT_R10*4)(r31) 470 lwz r11,_UC_GREGS+(PT_R11*4)(r31) 471 lwz r12,_UC_GREGS+(PT_R12*4)(r31) 472 lwz r13,_UC_GREGS+(PT_R13*4)(r31) 473 lwz r14,_UC_GREGS+(PT_R14*4)(r31) 474 lwz r15,_UC_GREGS+(PT_R15*4)(r31) 475 lwz r16,_UC_GREGS+(PT_R16*4)(r31) 476 lwz r17,_UC_GREGS+(PT_R17*4)(r31) 477 lwz r18,_UC_GREGS+(PT_R18*4)(r31) 478 lwz r19,_UC_GREGS+(PT_R19*4)(r31) 479 lwz r20,_UC_GREGS+(PT_R20*4)(r31) 480 lwz r21,_UC_GREGS+(PT_R21*4)(r31) 481 lwz r22,_UC_GREGS+(PT_R22*4)(r31) 482 lwz r23,_UC_GREGS+(PT_R23*4)(r31) 483 lwz r24,_UC_GREGS+(PT_R24*4)(r31) 484 lwz r25,_UC_GREGS+(PT_R25*4)(r31) 485 lwz r26,_UC_GREGS+(PT_R26*4)(r31) 486 lwz r27,_UC_GREGS+(PT_R27*4)(r31) 487 lwz r28,_UC_GREGS+(PT_R28*4)(r31) 488 lwz r29,_UC_GREGS+(PT_R29*4)(r31) 489 lwz r30,_UC_GREGS+(PT_R30*4)(r31) 490 lwz r1,_UC_GREGS+(PT_R1*4)(r31) 491 lwz r31,_UC_GREGS+(PT_R31*4)(r31) 492 493 bctr 494 4953:/*L(error_exit):*/ 496 lwz r0,_FRAME_LR_SAVE+16(r1) 497 addi r1,r1,16 498 mtlr r0 499 blr 500 501END(__CONTEXT_FUNC_NAME) 502