1/* 2 * Copyright (C) 2023 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#ifndef ART_RUNTIME_ARCH_RISCV64_ASM_SUPPORT_RISCV64_S_ 18#define ART_RUNTIME_ARCH_RISCV64_ASM_SUPPORT_RISCV64_S_ 19 20#include "asm_support_riscv64.h" 21#include "interpreter/cfi_asm_support.h" 22 23// Define special registers. 24 25// Register holding Thread::Current(). 26#define xSELF s1 27 28 29.macro ENTRY name 30 .hidden \name // Hide this as a global symbol, so we do not incur plt calls. 31 .global \name 32 .balign 16 33\name: 34 .cfi_startproc 35.endm 36 37 38.macro END name 39 .cfi_endproc 40 .size \name, .-\name 41.endm 42 43 44.macro UNDEFINED name 45 ENTRY \name 46 unimp 47 END \name 48.endm 49 50 51.macro CFI_REMEMBER_STATE 52 .cfi_remember_state 53.endm 54 55 56// The spec is not clear whether the CFA is part of the saved state and tools differ in the 57// behaviour, so explicitly set the CFA to avoid any ambiguity. 58// The restored CFA state should match the CFA state during CFI_REMEMBER_STATE. 59.macro CFI_RESTORE_STATE_AND_DEF_CFA reg, offset 60 .cfi_restore_state 61 .cfi_def_cfa \reg, \offset 62.endm 63 64 65.macro CFI_EXPRESSION_BREG n, b, offset 66 .if (-0x40 <= (\offset)) && ((\offset) < 0x40) 67 CFI_EXPRESSION_BREG_1(\n, \b, \offset) 68 .elseif (-0x2000 <= (\offset)) && ((\offset) < 0x2000) 69 CFI_EXPRESSION_BREG_2(\n, \b, \offset) 70 .else 71 .error "Unsupported offset" 72 .endif 73.endm 74 75 76.macro CFI_DEF_CFA_BREG_PLUS_UCONST reg, offset, size 77 .if (((\offset) < -0x40) || ((\offset) >= 0x40)) 78 .error "Unsupported offset" 79 .endif 80 81 .if ((\size) < 0) 82 .error "Unsupported size, negative" 83 .elseif ((\size) < 0x80) 84 CFI_DEF_CFA_BREG_PLUS_UCONST_1_1(\reg, \offset, \size) 85 .elseif ((\size) < 0x4000) 86 CFI_DEF_CFA_BREG_PLUS_UCONST_1_2(\reg, \offset, \size) 87 .else 88 .error "Unsupported size, too large" 89 .endif 90.endm 91 92 93// Macro to poison (negate) the reference for heap poisoning. 94.macro POISON_HEAP_REF ref 95#ifdef USE_HEAP_POISONING 96 neg \ref, \ref 97 zext.w \ref, \ref 98#endif // USE_HEAP_POISONING 99.endm 100 101 102// Macro to unpoison (negate) the reference for heap poisoning. 103.macro UNPOISON_HEAP_REF ref 104#ifdef USE_HEAP_POISONING 105 neg \ref, \ref 106 zext.w \ref, \ref 107#endif // USE_HEAP_POISONING 108.endm 109 110 111.macro INCREASE_FRAME frame_adjustment 112 addi sp, sp, -(\frame_adjustment) 113 .cfi_adjust_cfa_offset (\frame_adjustment) 114.endm 115 116 117.macro DECREASE_FRAME frame_adjustment 118 addi sp, sp, (\frame_adjustment) 119 .cfi_adjust_cfa_offset -(\frame_adjustment) 120.endm 121 122 123.macro SAVE_GPR_BASE base, reg, offset 124 sd \reg, (\offset)(\base) 125 .cfi_rel_offset \reg, (\offset) 126.endm 127 128 129.macro SAVE_GPR reg, offset 130 SAVE_GPR_BASE sp, \reg, \offset 131.endm 132 133 134.macro RESTORE_GPR_BASE base, reg, offset 135 ld \reg, (\offset)(\base) 136 .cfi_restore \reg 137.endm 138 139 140.macro RESTORE_GPR reg, offset 141 RESTORE_GPR_BASE sp, \reg, \offset 142.endm 143 144 145.macro RESTORE_GPR_NE skip, reg, offset 146 .ifnc \skip, \reg 147 RESTORE_GPR_BASE sp, \reg, \offset 148 .endif 149.endm 150 151 152.macro SAVE_FPR reg, offset 153 fsd \reg, (\offset)(sp) 154 .cfi_rel_offset \reg, (\offset) 155.endm 156 157 158.macro RESTORE_FPR reg, offset 159 fld \reg, (\offset)(sp) 160 .cfi_restore \reg 161.endm 162 163 164// 8 argument GPRS: a0 - a7 and 8 argument FPRs: fa0 - fa7 165#define ALL_ARGS_SIZE (8 * (8 + 8)) 166 167 168.macro SAVE_ALL_ARGS_INCREASE_FRAME extra_space 169 // Reserve space for all argument registers, plus the extra space. 170 INCREASE_FRAME (ALL_ARGS_SIZE + \extra_space) 171 172 // Argument GPRs a0 - a7. 173 sd a0, (8*0)(sp) 174 sd a1, (8*1)(sp) 175 sd a2, (8*2)(sp) 176 sd a3, (8*3)(sp) 177 sd a4, (8*4)(sp) 178 sd a5, (8*5)(sp) 179 sd a6, (8*6)(sp) 180 sd a7, (8*7)(sp) 181 182 // Argument FPRs fa0 - fa7. 183 fsd fa0, (8*8)(sp) 184 fsd fa1, (8*9)(sp) 185 fsd fa2, (8*10)(sp) 186 fsd fa3, (8*11)(sp) 187 fsd fa4, (8*12)(sp) 188 fsd fa5, (8*13)(sp) 189 fsd fa6, (8*14)(sp) 190 fsd fa7, (8*15)(sp) 191.endm 192 193 194.macro RESTORE_ALL_ARGS_DECREASE_FRAME extra_space 195 // Argument GPRs a0 - a7. 196 ld a0, (8*0)(sp) 197 ld a1, (8*1)(sp) 198 ld a2, (8*2)(sp) 199 ld a3, (8*3)(sp) 200 ld a4, (8*4)(sp) 201 ld a5, (8*5)(sp) 202 ld a6, (8*6)(sp) 203 ld a7, (8*7)(sp) 204 205 // Argument FPRs fa0 - fa7. 206 fld fa0, (8*8)(sp) 207 fld fa1, (8*9)(sp) 208 fld fa2, (8*10)(sp) 209 fld fa3, (8*11)(sp) 210 fld fa4, (8*12)(sp) 211 fld fa5, (8*13)(sp) 212 fld fa6, (8*14)(sp) 213 fld fa7, (8*15)(sp) 214 215 DECREASE_FRAME (ALL_ARGS_SIZE + \extra_space) 216.endm 217 218 219.macro LOAD_RUNTIME_INSTANCE reg 220#if __has_feature(hwaddress_sanitizer) 221#error "ART does not support HWASAN on RISC-V yet" 222#else 223 la \reg, _ZN3art7Runtime9instance_E 224#endif 225 ld \reg, 0(\reg) 226.endm 227 228 229// We need to save callee-save GPRs on the stack as they may contain references, and must be 230// visible to GC (unless the called method holds mutator lock and prevents GC from happening). 231// FP callee-saves shall be preserved by whatever runtime function we call, so they do not need 232// to be saved. 233.macro SETUP_SAVE_REFS_AND_ARGS_FRAME_INTERNAL 234#if (FRAME_SIZE_SAVE_REFS_AND_ARGS != 8*(1 + 8 + 7 + 11 + 1)) 235#error "FRAME_SIZE_SAVE_REFS_AND_ARGS(RISCV64) size not as expected." 236#endif 237 // stack slot (0*8)(sp) is for ArtMethod* 238 239 SAVE_FPR fa0, (1*8) 240 SAVE_FPR fa1, (2*8) 241 SAVE_FPR fa2, (3*8) 242 SAVE_FPR fa3, (4*8) 243 SAVE_FPR fa4, (5*8) 244 SAVE_FPR fa5, (6*8) 245 SAVE_FPR fa6, (7*8) 246 SAVE_FPR fa7, (8*8) 247 248 SAVE_GPR fp, (9*8) // x8, frame pointer 249 // s1 (x9) is the ART thread register 250 251 // a0 (x10) is the method pointer 252 SAVE_GPR a1, (10*8) // x11 253 SAVE_GPR a2, (11*8) // x12 254 SAVE_GPR a3, (12*8) // x13 255 SAVE_GPR a4, (13*8) // x14 256 SAVE_GPR a5, (14*8) // x15 257 SAVE_GPR a6, (15*8) // x16 258 SAVE_GPR a7, (16*8) // x17 259 260 SAVE_GPR s2, (17*8) // x18 261 SAVE_GPR s3, (18*8) // x19 262 SAVE_GPR s4, (19*8) // x20 263 SAVE_GPR s5, (20*8) // x21 264 SAVE_GPR s6, (21*8) // x22 265 SAVE_GPR s7, (22*8) // x23 266 SAVE_GPR s8, (23*8) // x24 267 SAVE_GPR s9, (24*8) // x25 268 SAVE_GPR s10, (25*8) // x26 269 SAVE_GPR s11, (26*8) // x27 270 271 SAVE_GPR ra, (27*8) // x1, return address 272.endm 273 274 275.macro RESTORE_SAVE_REFS_AND_ARGS_FRAME_INTERNAL 276 // stack slot (0*8)(sp) is for ArtMethod* 277 278 RESTORE_FPR fa0, (1*8) 279 RESTORE_FPR fa1, (2*8) 280 RESTORE_FPR fa2, (3*8) 281 RESTORE_FPR fa3, (4*8) 282 RESTORE_FPR fa4, (5*8) 283 RESTORE_FPR fa5, (6*8) 284 RESTORE_FPR fa6, (7*8) 285 RESTORE_FPR fa7, (8*8) 286 287 RESTORE_GPR fp, (9*8) // x8, frame pointer 288 289 // a0 is the method pointer 290 RESTORE_GPR a1, (10*8) // x11 291 RESTORE_GPR a2, (11*8) // x12 292 RESTORE_GPR a3, (12*8) // x13 293 RESTORE_GPR a4, (13*8) // x14 294 RESTORE_GPR a5, (14*8) // x15 295 RESTORE_GPR a6, (15*8) // x16 296 RESTORE_GPR a7, (16*8) // x17 297 298 // s1 is the ART thread register 299 RESTORE_GPR s2, (17*8) // x18 300 RESTORE_GPR s3, (18*8) // x19 301 RESTORE_GPR s4, (19*8) // x20 302 RESTORE_GPR s5, (20*8) // x21 303 RESTORE_GPR s6, (21*8) // x22 304 RESTORE_GPR s7, (22*8) // x23 305 RESTORE_GPR s8, (23*8) // x24 306 RESTORE_GPR s9, (24*8) // x25 307 RESTORE_GPR s10, (25*8) // x26 308 RESTORE_GPR s11, (26*8) // x27 309 310 RESTORE_GPR ra, (27*8) // x1, return address 311.endm 312 313 314.macro SETUP_CALLEE_SAVE_FRAME_COMMON_INTERNAL reg 315 // ArtMethod* is in reg, store it at the bottom of the stack. 316 sd \reg, (sp) 317 318 // Place sp in Thread::Current()->top_quick_frame. 319 sd sp, THREAD_TOP_QUICK_FRAME_OFFSET(xSELF) 320.endm 321 322 323.macro SETUP_CALLEE_SAVE_FRAME_COMMON tmpreg, runtime_method_offset 324 // art::Runtime* tmpreg = art::Runtime::instance_; 325 LOAD_RUNTIME_INSTANCE \tmpreg 326 327 // ArtMethod* tmpreg = Runtime::instance_->callee_save_methods_[<callee-save-frame-type>]; 328 ld \tmpreg, \runtime_method_offset(\tmpreg) 329 330 SETUP_CALLEE_SAVE_FRAME_COMMON_INTERNAL \tmpreg 331.endm 332 333 334.macro SETUP_SAVE_REFS_AND_ARGS_FRAME 335 INCREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS 336 SETUP_SAVE_REFS_AND_ARGS_FRAME_INTERNAL 337 SETUP_CALLEE_SAVE_FRAME_COMMON t0, RUNTIME_SAVE_REFS_AND_ARGS_METHOD_OFFSET 338.endm 339 340 341.macro SETUP_SAVE_REFS_AND_ARGS_FRAME_WITH_METHOD_IN_A0 342 INCREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS 343 SETUP_SAVE_REFS_AND_ARGS_FRAME_INTERNAL 344 SETUP_CALLEE_SAVE_FRAME_COMMON_INTERNAL a0 345.endm 346 347 348.macro RESTORE_SAVE_REFS_AND_ARGS_FRAME 349 RESTORE_SAVE_REFS_AND_ARGS_FRAME_INTERNAL 350 DECREASE_FRAME FRAME_SIZE_SAVE_REFS_AND_ARGS 351.endm 352 353 354.macro SAVE_ALL_CALLEE_SAVES 355#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVES != 8*(12 + 11 + 1 + 1 + 1)) 356#error "FRAME_SIZE_SAVE_ALL_CALLEE_SAVES(RISCV64) size not as expected." 357#endif 358 // stack slot (0*8)(sp) is for ArtMethod* 359 // stack slot (1*8)(sp) is for padding 360 361 // FP callee-saves. 362 SAVE_FPR fs0, (8*2) // f8 363 SAVE_FPR fs1, (8*3) // f9 364 SAVE_FPR fs2, (8*4) // f18 365 SAVE_FPR fs3, (8*5) // f19 366 SAVE_FPR fs4, (8*6) // f20 367 SAVE_FPR fs5, (8*7) // f21 368 SAVE_FPR fs6, (8*8) // f22 369 SAVE_FPR fs7, (8*9) // f23 370 SAVE_FPR fs8, (8*10) // f24 371 SAVE_FPR fs9, (8*11) // f25 372 SAVE_FPR fs10, (8*12) // f26 373 SAVE_FPR fs11, (8*13) // f27 374 375 // GP callee-saves 376 SAVE_GPR s0, (8*14) // x8/fp, frame pointer 377 // s1 (x9) is the ART thread register 378 SAVE_GPR s2, (8*15) // x18 379 SAVE_GPR s3, (8*16) // x19 380 SAVE_GPR s4, (8*17) // x20 381 SAVE_GPR s5, (8*18) // x21 382 SAVE_GPR s6, (8*19) // x22 383 SAVE_GPR s7, (8*20) // x23 384 SAVE_GPR s8, (8*21) // x24 385 SAVE_GPR s9, (8*22) // x25 386 SAVE_GPR s10, (8*23) // x26 387 SAVE_GPR s11, (8*24) // x27 388 389 SAVE_GPR ra, (8*25) // x1, return address 390.endm 391 392 393.macro RESTORE_ALL_CALLEE_SAVES 394#if (FRAME_SIZE_SAVE_ALL_CALLEE_SAVES != 8*(12 + 11 + 1 + 1 + 1)) 395#error "FRAME_SIZE_SAVE_ALL_CALLEE_SAVES(RISCV64) size not as expected." 396#endif 397 // stack slot (8*0)(sp) is for ArtMethod* 398 // stack slot (8*1)(sp) is for padding 399 400 // FP callee-saves. 401 RESTORE_FPR fs0, (8*2) // f8 402 RESTORE_FPR fs1, (8*3) // f9 403 RESTORE_FPR fs2, (8*4) // f18 404 RESTORE_FPR fs3, (8*5) // f19 405 RESTORE_FPR fs4, (8*6) // f20 406 RESTORE_FPR fs5, (8*7) // f21 407 RESTORE_FPR fs6, (8*8) // f22 408 RESTORE_FPR fs7, (8*9) // f23 409 RESTORE_FPR fs8, (8*10) // f24 410 RESTORE_FPR fs9, (8*11) // f25 411 RESTORE_FPR fs10, (8*12) // f26 412 RESTORE_FPR fs11, (8*13) // f27 413 414 // GP callee-saves 415 RESTORE_GPR s0, (8*14) // x8/fp, frame pointer 416 // s1 is the ART thread register 417 RESTORE_GPR s2, (8*15) // x18 418 RESTORE_GPR s3, (8*16) // x19 419 RESTORE_GPR s4, (8*17) // x20 420 RESTORE_GPR s5, (8*18) // x21 421 RESTORE_GPR s6, (8*19) // x22 422 RESTORE_GPR s7, (8*20) // x23 423 RESTORE_GPR s8, (8*21) // x24 424 RESTORE_GPR s9, (8*22) // x25 425 RESTORE_GPR s10, (8*23) // x26 426 RESTORE_GPR s11, (8*24) // x27 427 428 RESTORE_GPR ra, (8*25) // x1, return address 429.endm 430 431 432.macro SETUP_SAVE_ALL_CALLEE_SAVES_FRAME 433 INCREASE_FRAME FRAME_SIZE_SAVE_ALL_CALLEE_SAVES 434 SAVE_ALL_CALLEE_SAVES 435 SETUP_CALLEE_SAVE_FRAME_COMMON t0, RUNTIME_SAVE_ALL_CALLEE_SAVES_METHOD_OFFSET 436.endm 437 438 439.macro SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP_SKIP_RA \ 440 runtime_method_offset = RUNTIME_SAVE_EVERYTHING_METHOD_OFFSET 441#if (FRAME_SIZE_SAVE_EVERYTHING != 8*(1 + 32 + 27)) 442#error "FRAME_SIZE_SAVE_EVERYTHING(RISCV64) size not as expected." 443#endif 444 // stack slot (8*0)(sp) is for ArtMethod* 445 446 // 32 slots for FPRs 447 SAVE_FPR ft0, 8*1 // f0 448 SAVE_FPR ft1, 8*2 // f1 449 SAVE_FPR ft2, 8*3 // f2 450 SAVE_FPR ft3, 8*4 // f3 451 SAVE_FPR ft4, 8*5 // f4 452 SAVE_FPR ft5, 8*6 // f5 453 SAVE_FPR ft6, 8*7 // f6 454 SAVE_FPR ft7, 8*8 // f7 455 SAVE_FPR fs0, 8*9 // f8 456 SAVE_FPR fs1, 8*10 // f9 457#define SAVE_EVERYTHING_FRAME_OFFSET_FA0 (8*11) 458 SAVE_FPR fa0, 8*11 // f10, its offset must equal SAVE_EVERYTHING_FRAME_OFFSET_FA0 459 SAVE_FPR fa1, 8*12 // f11 460 SAVE_FPR fa2, 8*13 // f12 461 SAVE_FPR fa3, 8*14 // f13 462 SAVE_FPR fa4, 8*15 // f14 463 SAVE_FPR fa5, 8*16 // f15 464 SAVE_FPR fa6, 8*17 // f16 465 SAVE_FPR fa7, 8*18 // f17 466 SAVE_FPR fs2, 8*19 // f18 467 SAVE_FPR fs3, 8*20 // f19 468 SAVE_FPR fs4, 8*21 // f20 469 SAVE_FPR fs5, 8*22 // f21 470 SAVE_FPR fs6, 8*23 // f22 471 SAVE_FPR fs7, 8*24 // f23 472 SAVE_FPR fs8, 8*25 // f24 473 SAVE_FPR fs9, 8*26 // f25 474 SAVE_FPR fs10, 8*27 // f26 475 SAVE_FPR fs11, 8*28 // f27 476 SAVE_FPR ft8, 8*29 // f28 477 SAVE_FPR ft9, 8*30 // f29 478 SAVE_FPR ft10, 8*31 // f30 479 SAVE_FPR ft11, 8*32 // f31 480 481 // 27 slots for GPRs (excluded: zero/x0, sp/x2, gp/x3, tp/x4, s1/x9 -- the ART thread register) 482 SAVE_GPR t0, 8*33 // x5 483 SAVE_GPR t1, 8*34 // x6 484 SAVE_GPR t2, 8*35 // x7 485 SAVE_GPR s0, 8*36 // x8 486#define SAVE_EVERYTHING_FRAME_OFFSET_A0 (8*37) 487 SAVE_GPR a0, 8*37 // x10, its offset must equal SAVE_EVERYTHING_FRAME_OFFSET_A0 488 SAVE_GPR a1, 8*38 // x11 489 SAVE_GPR a2, 8*39 // x12 490 SAVE_GPR a3, 8*40 // x13 491 SAVE_GPR a4, 8*41 // x14 492 SAVE_GPR a5, 8*42 // x15 493 SAVE_GPR a6, 8*43 // x16 494 SAVE_GPR a7, 8*44 // x17 495 SAVE_GPR s2, 8*45 // x18 496 SAVE_GPR s3, 8*46 // x19 497 SAVE_GPR s4, 8*47 // x20 498 SAVE_GPR s5, 8*48 // x21 499 SAVE_GPR s6, 8*49 // x22 500 SAVE_GPR s7, 8*50 // x23 501 SAVE_GPR s8, 8*51 // x24 502 SAVE_GPR s9, 8*52 // x25 503 SAVE_GPR s10, 8*53 // x26 504 SAVE_GPR s11, 8*54 // x27 505 SAVE_GPR t3, 8*55 // x28 506 SAVE_GPR t4, 8*56 // x29 507 SAVE_GPR t5, 8*57 // x30 508 SAVE_GPR t6, 8*58 // x31 509 510 // RA already saved by the user of this macro. 511 512 SETUP_CALLEE_SAVE_FRAME_COMMON t0, \runtime_method_offset 513.endm 514 515 516.macro SETUP_SAVE_EVERYTHING_FRAME runtime_method_offset = RUNTIME_SAVE_EVERYTHING_METHOD_OFFSET 517#if (FRAME_SIZE_SAVE_EVERYTHING != 8*(1 + 32 + 27)) 518#error "FRAME_SIZE_SAVE_EVERYTHING(RISCV64) size not as expected." 519#endif 520 INCREASE_FRAME FRAME_SIZE_SAVE_EVERYTHING 521 SAVE_GPR ra, 8*59 // x1, return address 522 SETUP_SAVE_EVERYTHING_FRAME_DECREMENTED_SP_SKIP_RA \runtime_method_offset 523.endm 524 525 526.macro RESTORE_SAVE_EVERYTHING_FRAME load_a0 = 1 527 // stack slot (8*0)(sp) is for ArtMethod* 528 529 // 32 slots for FPRs 530 RESTORE_FPR ft0, (8*1) // f0 531 RESTORE_FPR ft1, (8*2) // f1 532 RESTORE_FPR ft2, (8*3) // f2 533 RESTORE_FPR ft3, (8*4) // f3 534 RESTORE_FPR ft4, (8*5) // f4 535 RESTORE_FPR ft5, (8*6) // f5 536 RESTORE_FPR ft6, (8*7) // f6 537 RESTORE_FPR ft7, (8*8) // f7 538 RESTORE_FPR fs0, (8*9) // f8 539 RESTORE_FPR fs1, (8*10) // f9 540#if SAVE_EVERYTHING_FRAME_OFFSET_FA0 != (8*11) 541#error "unexpected SAVE_EVERYTHING_FRAME_OFFSET_FA0" 542#endif 543 RESTORE_FPR fa0, (8*11) // f10, offset must equal SAVE_EVERYTHING_FRAME_OFFSET_FA0 544 RESTORE_FPR fa1, (8*12) // f11 545 RESTORE_FPR fa2, (8*13) // f12 546 RESTORE_FPR fa3, (8*14) // f13 547 RESTORE_FPR fa4, (8*15) // f14 548 RESTORE_FPR fa5, (8*16) // f15 549 RESTORE_FPR fa6, (8*17) // f16 550 RESTORE_FPR fa7, (8*18) // f17 551 RESTORE_FPR fs2, (8*19) // f18 552 RESTORE_FPR fs3, (8*20) // f19 553 RESTORE_FPR fs4, (8*21) // f20 554 RESTORE_FPR fs5, (8*22) // f21 555 RESTORE_FPR fs6, (8*23) // f22 556 RESTORE_FPR fs7, (8*24) // f23 557 RESTORE_FPR fs8, (8*25) // f24 558 RESTORE_FPR fs9, (8*26) // f25 559 RESTORE_FPR fs10, (8*27) // f26 560 RESTORE_FPR fs11, (8*28) // f27 561 RESTORE_FPR ft8, (8*29) // f28 562 RESTORE_FPR ft9, (8*30) // f29 563 RESTORE_FPR ft10, (8*31) // f30 564 RESTORE_FPR ft11, (8*32) // f31 565 566 // 26 slots for GPRs (excluded: zero/x0, sp/x2, gp/x3, tp/x4, s1/x9 -- the ART thread register) 567 RESTORE_GPR t0, (8*33) // x5 568 RESTORE_GPR t1, (8*34) // x6 569 RESTORE_GPR t2, (8*35) // x7 570 RESTORE_GPR s0, (8*36) // x8 571#if SAVE_EVERYTHING_FRAME_OFFSET_A0 != (8*37) 572#error "unexpected SAVE_EVERYTHING_FRAME_OFFSET_A0" 573#endif 574 .if \load_a0 575 RESTORE_GPR a0, (8*37) // x10, offset must equal SAVE_EVERYTHING_FRAME_OFFSET_A0 576 .endif 577 RESTORE_GPR a1, (8*38) // x11 578 RESTORE_GPR a2, (8*39) // x12 579 RESTORE_GPR a3, (8*40) // x13 580 RESTORE_GPR a4, (8*41) // x14 581 RESTORE_GPR a5, (8*42) // x15 582 RESTORE_GPR a6, (8*43) // x16 583 RESTORE_GPR a7, (8*44) // x17 584 RESTORE_GPR s2, (8*45) // x18 585 RESTORE_GPR s3, (8*46) // x19 586 RESTORE_GPR s4, (8*47) // x20 587 RESTORE_GPR s5, (8*48) // x21 588 RESTORE_GPR s6, (8*49) // x22 589 RESTORE_GPR s7, (8*50) // x23 590 RESTORE_GPR s8, (8*51) // x24 591 RESTORE_GPR s9, (8*52) // x25 592 RESTORE_GPR s10, (8*53) // x26 593 RESTORE_GPR s11, (8*54) // x27 594 RESTORE_GPR t3, (8*55) // x28 595 RESTORE_GPR t4, (8*56) // x29 596 RESTORE_GPR t5, (8*57) // x30 597 RESTORE_GPR t6, (8*58) // x31 598 599 RESTORE_GPR ra, (8*59) // x1, return address 600 601 DECREASE_FRAME FRAME_SIZE_SAVE_EVERYTHING 602.endm 603 604 605// For compatibility with Runtime::CreateCalleeSaveMethod(kSaveRefsOnly). 606.macro SETUP_SAVE_REFS_ONLY_FRAME 607 INCREASE_FRAME FRAME_SIZE_SAVE_REFS_ONLY 608 609 // stack slot (8*0)(sp) is for ArtMethod* 610 // stack slot (8*1)(sp) is for padding 611 SAVE_GPR s0, (8*2) // x8 612 SAVE_GPR s2, (8*3) // x18 613 SAVE_GPR s3, (8*4) // x19 614 SAVE_GPR s4, (8*5) // x20 615 SAVE_GPR s5, (8*6) // x21 616 SAVE_GPR s6, (8*7) // x22 617 SAVE_GPR s7, (8*8) // x23 618 SAVE_GPR s8, (8*9) // x24 619 SAVE_GPR s9, (8*10) // x25 620 SAVE_GPR s10, (8*11) // x26 621 SAVE_GPR s11, (8*12) // x27 622 SAVE_GPR ra, (8*13) // x1 623 624 SETUP_CALLEE_SAVE_FRAME_COMMON t0, RUNTIME_SAVE_REFS_ONLY_METHOD_OFFSET 625.endm 626 627 628.macro RESTORE_SAVE_REFS_ONLY_FRAME 629 // stack slot (8*0)(sp) is for ArtMethod* 630 // stack slot (8*1)(sp) is for padding 631 RESTORE_GPR s0, (8*2) // x8 632 RESTORE_GPR s2, (8*3) // x18 633 RESTORE_GPR s3, (8*4) // x19 634 RESTORE_GPR s4, (8*5) // x20 635 RESTORE_GPR s5, (8*6) // x21 636 RESTORE_GPR s6, (8*7) // x22 637 RESTORE_GPR s7, (8*8) // x23 638 RESTORE_GPR s8, (8*9) // x24 639 RESTORE_GPR s9, (8*10) // x25 640 RESTORE_GPR s10, (8*11) // x26 641 RESTORE_GPR s11, (8*12) // x27 642 RESTORE_GPR ra, (8*13) // x1 643 644 DECREASE_FRAME FRAME_SIZE_SAVE_REFS_ONLY 645.endm 646 647 648// CFI note. This macro is used where the CFA rule is a dwarf expression, so adjustment of SP does 649// not affect CFA computation. We also elide CFI descriptors for the argument registers, because 650// they can be recovered from the stack in a debugging scenario. 651.macro SPILL_ALL_ARGUMENTS 652#if (FRAME_SIZE_SAVE_ARGS_ONLY != 128) 653#error "FRAME_SIZE_SAVE_ARGS_ONLY(riscv64) not as expected." 654#endif 655 addi sp, sp, -FRAME_SIZE_SAVE_ARGS_ONLY 656 sd a0, (8*0)(sp) 657 sd a1, (8*1)(sp) 658 sd a2, (8*2)(sp) 659 sd a3, (8*3)(sp) 660 sd a4, (8*4)(sp) 661 sd a5, (8*5)(sp) 662 sd a6, (8*6)(sp) 663 sd a7, (8*7)(sp) 664 fsd fa0, (8*8)(sp) 665 fsd fa1, (8*9)(sp) 666 fsd fa2, (8*10)(sp) 667 fsd fa3, (8*11)(sp) 668 fsd fa4, (8*12)(sp) 669 fsd fa5, (8*13)(sp) 670 fsd fa6, (8*14)(sp) 671 fsd fa7, (8*15)(sp) 672.endm 673 674 675.macro RESTORE_ALL_ARGUMENTS 676 ld a0, (8*0)(sp) 677 ld a1, (8*1)(sp) 678 ld a2, (8*2)(sp) 679 ld a3, (8*3)(sp) 680 ld a4, (8*4)(sp) 681 ld a5, (8*5)(sp) 682 ld a6, (8*6)(sp) 683 ld a7, (8*7)(sp) 684 fld fa0, (8*8)(sp) 685 fld fa1, (8*9)(sp) 686 fld fa2, (8*10)(sp) 687 fld fa3, (8*11)(sp) 688 fld fa4, (8*12)(sp) 689 fld fa5, (8*13)(sp) 690 fld fa6, (8*14)(sp) 691 fld fa7, (8*15)(sp) 692 addi sp, sp, FRAME_SIZE_SAVE_ARGS_ONLY 693.endm 694 695 696.macro SETUP_NTERP_SAVE_CALLEE_SAVES 697#if (NTERP_SIZE_SAVE_CALLEE_SAVES != 8*(12 + 1 + 10 + 1)) 698#error "NTERP_SIZE_SAVE_CALLEE_SAVES(RISCV64) size not as expected." 699#endif 700 // FP callee-saves. 701 SAVE_FPR fs0, (8*0) // f8 702 SAVE_FPR fs1, (8*1) // f9 703 SAVE_FPR fs2, (8*2) // f18 704 SAVE_FPR fs3, (8*3) // f19 705 SAVE_FPR fs4, (8*4) // f20 706 SAVE_FPR fs5, (8*5) // f21 707 SAVE_FPR fs6, (8*6) // f22 708 SAVE_FPR fs7, (8*7) // f23 709 SAVE_FPR fs8, (8*8) // f24 710 SAVE_FPR fs9, (8*9) // f25 711 SAVE_FPR fs10, (8*10) // f26 712 SAVE_FPR fs11, (8*11) // f27 713 714 // GP callee-saves 715 SAVE_GPR s0, (8*12) // x8/fp, frame pointer 716 // s1 (x9) is the ART thread register 717 SAVE_GPR s2, (8*13) // x18 718 SAVE_GPR s3, (8*14) // x19 719 SAVE_GPR s4, (8*15) // x20 720 SAVE_GPR s5, (8*16) // x21 721 SAVE_GPR s6, (8*17) // x22 722 SAVE_GPR s7, (8*18) // x23 723 SAVE_GPR s8, (8*19) // x24 724 SAVE_GPR s9, (8*20) // x25 725 SAVE_GPR s10, (8*21) // x26 726 SAVE_GPR s11, (8*22) // x27 727 728 SAVE_GPR ra, (8*23) // x1, return address 729.endm 730 731 732.macro RESTORE_NTERP_SAVE_CALLEE_SAVES 733#if (NTERP_SIZE_SAVE_CALLEE_SAVES != 8*(12 + 1 + 10 + 1)) 734#error "NTERP_SIZE_SAVE_CALLEE_SAVES(RISCV64) size not as expected." 735#endif 736 // FP callee-saves. 737 RESTORE_FPR fs0, (8*0) // f8 738 RESTORE_FPR fs1, (8*1) // f9 739 RESTORE_FPR fs2, (8*2) // f18 740 RESTORE_FPR fs3, (8*3) // f19 741 RESTORE_FPR fs4, (8*4) // f20 742 RESTORE_FPR fs5, (8*5) // f21 743 RESTORE_FPR fs6, (8*6) // f22 744 RESTORE_FPR fs7, (8*7) // f23 745 RESTORE_FPR fs8, (8*8) // f24 746 RESTORE_FPR fs9, (8*9) // f25 747 RESTORE_FPR fs10, (8*10) // f26 748 RESTORE_FPR fs11, (8*11) // f27 749 750 // GP callee-saves 751 RESTORE_GPR s0, (8*12) // x8/fp, frame pointer 752 // s1 is the ART thread register 753 RESTORE_GPR s2, (8*13) // x18 754 RESTORE_GPR s3, (8*14) // x19 755 RESTORE_GPR s4, (8*15) // x20 756 RESTORE_GPR s5, (8*16) // x21 757 RESTORE_GPR s6, (8*17) // x22 758 RESTORE_GPR s7, (8*18) // x23 759 RESTORE_GPR s8, (8*19) // x24 760 RESTORE_GPR s9, (8*20) // x25 761 RESTORE_GPR s10, (8*21) // x26 762 RESTORE_GPR s11, (8*22) // x27 763 764 RESTORE_GPR ra, (8*23) // x1, return address 765.endm 766 767 768// Macro that calls through to artDeliverPendingExceptionFromCode, where the pending exception is 769// Thread::Current()->exception_ when the runtime method frame is ready. 770.macro DELIVER_PENDING_EXCEPTION_FRAME_READY 771 mv a0, xSELF 772 call artDeliverPendingExceptionFromCode 773 call art_quick_do_long_jump // (Context*) 774 unimp // Unreached 775.endm 776 777 778// Macro that calls through to artDeliverPendingExceptionFromCode, where the pending exception is 779// Thread::Current()->exception_. 780.macro DELIVER_PENDING_EXCEPTION 781 SETUP_SAVE_ALL_CALLEE_SAVES_FRAME 782 DELIVER_PENDING_EXCEPTION_FRAME_READY 783.endm 784 785 786.macro RETURN_OR_DELIVER_PENDING_EXCEPTION_REG reg 787 ld \reg, THREAD_EXCEPTION_OFFSET(xSELF) 788 bnez \reg, 1f 789 ret 7901: 791 DELIVER_PENDING_EXCEPTION 792.endm 793 794// Macro to emit a single LUI to load the given value while checking that the low 12 bits are zero. 795.macro LUI_VALUE reg, value 796 .if (\value & 0xfff) != 0 797 .error "Cannot use LUI to materialize a value with some of the low 12 bits set." 798 .endif 799 lui \reg, (\value) >> 12 800.endm 801 802 803// Locking is needed for both managed code and JNI stubs. 804.macro LOCK_OBJECT_FAST_PATH obj, slow_lock, can_be_null 805 // Use scratch registers T1-T6 as temporaries. 806 // Note: T0 is used as the argument register for `art_jni_lock_object` and passed as `obj`. 807 lw t2, THREAD_ID_OFFSET(xSELF) 808 .if \can_be_null 809 beqz \obj, \slow_lock 810 .endif 811 addi t1, \obj, MIRROR_OBJECT_LOCK_WORD_OFFSET // Exclusive load/store has no offset. 8121: 813 // Note: The LR/SC sequence must be at most 16 instructions, so we cannot have the 814 // recursive locking in a slow-path as on other architectures. 815 lr.w.aq t3, (t1) // Acquire needed only in most common case. 816 LUI_VALUE t5, LOCK_WORD_GC_STATE_MASK_SHIFTED // Prepare mask for testing non-gc bits. 817 xor t4, t3, t2 // Prepare the value to store if unlocked 818 // (thread id, count of 0 and preserved read barrier bits), 819 // or prepare to compare thread id for recursive lock check 820 // (lock_word.ThreadId() ^ self->ThreadId()). 821 or t6, t5, t3 // Test the non-gc bits. 822 beq t6, t5, 2f // Check if unlocked. 823 // Check lock word state and thread id together, 824 LUI_VALUE \ 825 t5, 0xffffffff ^ (LOCK_WORD_STATE_MASK_SHIFTED | LOCK_WORD_THIN_LOCK_OWNER_MASK_SHIFTED) 826 or t6, t5, t4 827 bne t6, t5, \slow_lock 828 LUI_VALUE t4, LOCK_WORD_THIN_LOCK_COUNT_ONE // Increment the recursive lock count. 829 addw t4, t3, t4 830 LUI_VALUE t5, LOCK_WORD_THIN_LOCK_COUNT_MASK_SHIFTED // Test the new thin lock count. 831 and t5, t4, t5 832 beqz t5, \slow_lock // Zero as the new count indicates overflow, go slow path. 8332: 834 // Store the prepared value: 835 // - if unlocked, original lock word plus thread id, 836 // - if already locked, original lock word plus incremented lock count. 837 sc.w t3, t4, (t1) 838 bnez t3, 1b // If the store failed, retry. 839 ret 840.endm 841 842// Unlocking is needed for both managed code and JNI stubs. 843.macro UNLOCK_OBJECT_FAST_PATH obj, slow_unlock, can_be_null 844 // Use scratch registers T1-T6 as temporaries. 845 // Note: T0 is used as the argument register for `art_jni_unlock_object` and passed as `obj`. 846 lw t2, THREAD_ID_OFFSET(xSELF) 847 .if \can_be_null 848 beqz \obj, \slow_unlock 849 .endif 850 addi t1, \obj, MIRROR_OBJECT_LOCK_WORD_OFFSET // Exclusive load/store has no offset. 8511: 852 // Note: Without read barriers, we could do plain LW here but there is no store-release 853 // other than SC on riscv64, so we do this with LR/SC for all cofigurations. 854 // Note: The LR/SC sequence must be at most 16 instructions, so we cannot have the 855 // recursive unlocking in a slow-path as on other architectures. 856 lr.w t3, (t1) 857 LUI_VALUE t5, LOCK_WORD_GC_STATE_MASK_SHIFTED // Prepare mask for testing non-gc bits. 858 xor t4, t3, t2 // Prepare the value to store if simply locked 859 // (mostly 0s, and preserved read barrier bits), 860 // or prepare to compare thread id for recursive lock check 861 // (lock_word.ThreadId() ^ self->ThreadId()). 862 or t6, t5, t4 // Test the non-gc bits. 863 beq t6, t5, 2f // Simply locked by this thread? 864 // Check lock word state and thread id together. 865 LUI_VALUE \ 866 t5, 0xffffffff ^ (LOCK_WORD_STATE_MASK_SHIFTED | LOCK_WORD_THIN_LOCK_OWNER_MASK_SHIFTED) 867 or t6, t5, t4 868 bne t6, t5, \slow_unlock 869 LUI_VALUE t4, LOCK_WORD_THIN_LOCK_COUNT_ONE // Decrement the recursive lock count. 870 subw t4, t3, t4 8712: 872 // Store the prepared value: 873 // - if simply locked, original lock word with removed thread id, 874 // - if recursively locked, original lock word plus decremented lock count. 875 sc.w.rl t3, t4, (t1) // Need to use atomic instructions for read barrier. 876 bnez t3, 1b // If the store failed, retry. 877 ret 878.endm 879 880 881// Macros to branch based on the value of a specific bit. 882.macro BRANCH_IF_BIT_CLEAR tmp, reg, bit, dest 883 slli \tmp, \reg, (63 - \bit) // tested bit => sign bit 884 bgez \tmp, \dest 885.endm 886 887 888.macro BRANCH_IF_BIT_SET tmp, reg, bit, dest 889 slli \tmp, \reg, (63 - \bit) // tested bit => sign bit 890 bltz \tmp, \dest 891.endm 892 893 894#endif // ART_RUNTIME_ARCH_RISCV64_ASM_SUPPORT_RISCV64_S_ 895