diff options
| -rw-r--r-- | runtime/arch/riscv64/quick_entrypoints_riscv64.S | 344 |
1 files changed, 136 insertions, 208 deletions
diff --git a/runtime/arch/riscv64/quick_entrypoints_riscv64.S b/runtime/arch/riscv64/quick_entrypoints_riscv64.S index 4c737dbe1d..bca933ab8c 100644 --- a/runtime/arch/riscv64/quick_entrypoints_riscv64.S +++ b/runtime/arch/riscv64/quick_entrypoints_riscv64.S @@ -41,15 +41,13 @@ END ExecuteSwitchImplAsm .macro INVOKE_STUB_CREATE_FRAME // Save ra, fp, xSELF (current thread) a4, a5 (they will be needed in the invoke stub return) // and callee-save regs s3 - s5 that are clobbered here and in art_quick_invoke_(static_)_stub. - INCREASE_FRAME 64 + INCREASE_FRAME 48 SAVE_GPR fp (8*0) SAVE_GPR xSELF (8*1) SAVE_GPR a4 (8*2) SAVE_GPR a5 (8*3) SAVE_GPR s3 (8*4) - SAVE_GPR s4 (8*5) - SAVE_GPR s5 (8*6) - SAVE_GPR ra (8*7) + SAVE_GPR ra (8*5) mv fp, sp // save frame pointer .cfi_def_cfa_register fp @@ -95,11 +93,8 @@ END ExecuteSwitchImplAsm RESTORE_GPR a4 (8*2) RESTORE_GPR a5 (8*3) RESTORE_GPR s3 (8*4) - RESTORE_GPR s4 (8*5) - RESTORE_GPR s5 (8*6) - RESTORE_GPR ra (8*7) - - DECREASE_FRAME 64 + RESTORE_GPR ra (8*5) + DECREASE_FRAME 48 // Load result type (1-byte symbol) from a5. // Check result type and store the correct register into the jvalue in memory at a4 address. @@ -135,127 +130,139 @@ ENTRY art_deliver_pending_exception END art_deliver_pending_exception -#define LOADREG_SIZE 10 - - -// Macro for loading a parameter into a register. Arguments: -// - counter: a register with offset into the jump table -// - register: the name of the register to be loaded -// - return: a label where to jump in the end -// S3 points to the next argument to be loaded (saved on stack by INVOKE_STUB_CREATE_FRAME). -.macro LOADREG_I4 counter register return - lw \register, (s3) - addi s3, s3, 4 - add \counter, \counter, LOADREG_SIZE - j \return -.endm -.macro LOADREG_I8 counter register return - ld \register, (s3) - addi s3, s3, 8 - add \counter, \counter, LOADREG_SIZE - j \return -.endm -.macro LOADREG_F4 counter register return - flw \register, (s3) - addi s3, s3, 4 - add \counter, \counter, LOADREG_SIZE - j \return -.endm -.macro LOADREG_F8 counter register return - fld \register, (s3) - addi s3, s3, 8 - add \counter, \counter, LOADREG_SIZE - j \return +// Macros for loading an argument into a register. +// label - the base name of the label of the load routine, +// reg - the register to load, +// args - pointer to current argument, incremented by size, +// size - the size of the register - 4 or 8 bytes, +// load - instruction used for loading, +// nh4_reg - the register to fill with the address of the next handler for 4-byte values, +// nh4_l - the base name of the label of the next handler for 4-byte values, +// nh8_reg - the register to fill with the address of the next handler for 8-byte values, +// nh8_l - the base name of the label of the next handler for 8-byte values, +// cont - the base name of the label for continuing the shorty processing loop, +// sfx - suffix added to all labels to make labels unique for different users. +.macro INVOKE_STUB_LOAD_REG label, reg, args, size, load, nh4_reg, nh4_l, nh8_reg, nh8_l, cont, sfx +\label\sfx: + \load \reg, (\args) + addi \args, \args, \size + la \nh4_reg, \nh4_l\sfx + la \nh8_reg, \nh8_l\sfx + j \cont\sfx .endm -// A debug mode macro that checks if the specified LOADREG_* procedure has the expected size. -// This is needed because we do not know in advance which instructions the assembler / linker may -// choose to compress, so we cannot determine procedure size from the number of instructions in it. -.macro LOADREG_SIZE_CHECK proc reg -#ifndef NDEBUG - la t0, 2f - la t1, 1f - sub t0, t0, t1 - li t1, LOADREG_SIZE - beq t0, t1, 2f // skip both SIGILL and the artificial LOADREG_* call - unimp // crash with SIGILL as the LOADREG_* macro has unexpected length -1: - \proc t0 \reg 2f // unreachable, arguments do not matter -2: -#endif +// Macro for skipping an argument that does not fit into argument registers. +// label - the base name of the label of the skip routine, +// args - pointer to current argument, incremented by size, +// size - the size of the argument - 4 or 8 bytes, +// cont - the base name of the label for continuing the shorty processing loop, +// sfx - suffix added to all labels to make labels unique for different users. +.macro INVOKE_STUB_SKIP_ARG label, args, size, cont, sfx +\label\sfx: + addi \args, \args, \size + j \cont\sfx .endm -.macro LOADREG_SIZE_CHECK_ALL - LOADREG_SIZE_CHECK LOADREG_I4 t0 - LOADREG_SIZE_CHECK LOADREG_I8 t0 - LOADREG_SIZE_CHECK LOADREG_F4 ft0 - LOADREG_SIZE_CHECK LOADREG_F8 ft0 -.endm - - -// Helper macro to share the common part of art_quick_invoke_stub and art_quick_invoke_static_stub. -// Fill registers a1 - a7 and fa0 - fa7 with parameters in a loop, parse shorty to determine which -// register to load next. Parameters that do not fit into registers remain on stack. -// -.macro INVOKE_STUB_LOOP maxgprs storeA4 storeA8 storeF4 storeF8 start end - LOADREG_SIZE_CHECK_ALL // check that the jump table below has expected slot size - - // Load addresses for routines that load registers. - la t3, \storeA4 - la t4, \storeA8 - la t5, \storeF4 - la t6, \storeF8 - - // Initialize routine offsets to 0 for integers (s4) and floating point (s5). - mv s4, zero - mv s5, zero - - mv t0, a5 // Load shorty address. +// Fill registers a1 to a7 and fa0 to fa7 with parameters. +// Parse the passed shorty to determine which register to load. +// a5 - shorty, +// s3 - points to arguments on the stack, +// sfx - suffix added to all labels to make labels unique for different users. +.macro INVOKE_STUB_LOAD_ALL_ARGS sfx + mv t0, a5 // Load shorty address, + addi t0, t0, 1 // plus one to skip the return type. + + // Load this (if instance method) and addresses for routines that load argument GPRs and FPRs. + .ifc \sfx, _instance + lw a1, (s3) // Load "this" parameter, + addi s3, s3, 4 // and increment arg pointer. + la t3, .Lload4i2\sfx + la t4, .Lload8i2\sfx + .else + la t3, .Lload4i1\sfx + la t4, .Lload8i1\sfx + .endif + la t5, .Lload4f0\sfx + la t6, .Lload8f0\sfx // Loop to fill registers. -\start: - addi t0, t0, 1 // Increment (first increment skips return type). - lb t1, (t0) // Load next character in signature. - beqz t1, \end // Exit at end of signature. Shorty is null-terminated. - - li t2, 'F' // Check if current shorty character is 'F' for float. - bne t1, t2, 1f - li t2, 8 * LOADREG_SIZE // Maximum 8 FPRs are available. - beq s5, t2, 4f // Skip this load if all registers full. - add t2, t5, s5 // Calculate subroutine to jump to for loading float in a register. - jr t2 - -1: - li t2, 'D' // Check if current shorty character is 'D' for double. - bne t1, t2, 2f - li t2, 8 * LOADREG_SIZE // Maximum 8 FPRs are available. - beq s5, t2, 5f // Skip this load if all registers full. - add t2, t6, s5 // Calculate subroutine to jump to for loading double in a register. - jr t2 - -2: - li t2, 'J' // Check if current shorty character is 'J' for long. - bne t1, t2, 3f - li t2, \maxgprs * LOADREG_SIZE - beq s4, t2, 5f // Skip this load if all registers full. - add t2, t4, s4 // Calculate subroutine to jump to for loading long in a register. - jr t2 - -3: // Everything else takes one vReg (4 bytes). - li t2, \maxgprs * LOADREG_SIZE - beq s4, t2, 4f // Skip this load if all registers full. - add t2, t3, s4 // Calculate subroutine to jump to for loading 4 bytes in a register. - jr t2 - -4: // advance 4 bytes - addi s3, s3, 4 - j \start - -5: // advance 8 bytes - addi s3, s3, 8 - j \start +.Lfill_regs\sfx: + lb t1, (t0) // Load next character in signature, and increment. + addi t0, t0, 1 // and increment. + beqz t1, .Lcall_method\sfx // Exit at end of signature. Shorty 0 terminated. + + li t2, 'J' + beq t1, t2, .Lload_long\sfx // Is this a long? + + li t2, 'F' + beq t1, t2, .Lload_float\sfx // Is this a float? + + li t2, 'D' + beq t1, t2, .Lload_double\sfx // Is this a double? + + // Everything else uses a 4-byte GPR. + jr t3 + +.Lload_long\sfx: + jr t4 + +.Lload_float\sfx: + jr t5 + +.Lload_double\sfx: + jr t6 + +// Handlers for loading other args (not float/double/long) into 4-byte GPRs. + .ifnc \sfx, _instance + INVOKE_STUB_LOAD_REG \ + .Lload4i1, a1, s3, 4, lw, t3, .Lload4i2, t4, .Lload8i2, .Lfill_regs, \sfx + .endif + INVOKE_STUB_LOAD_REG .Lload4i2, a2, s3, 4, lw, t3, .Lload4i3, t4, .Lload8i3, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload4i3, a3, s3, 4, lw, t3, .Lload4i4, t4, .Lload8i4, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload4i4, a4, s3, 4, lw, t3, .Lload4i5, t4, .Lload8i5, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload4i5, a5, s3, 4, lw, t3, .Lload4i6, t4, .Lload8i6, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload4i6, a6, s3, 4, lw, t3, .Lload4i7, t4, .Lload8i7, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload4i7, a7, s3, 4, lw, t3, .Lskip4, t4, .Lskip8, .Lfill_regs, \sfx + +// Handlers for loading longs into 8-byte GPRs. + .ifnc \sfx, _instance + INVOKE_STUB_LOAD_REG \ + .Lload8i1, a1, s3, 8, ld, t3, .Lload4i2, t4, .Lload8i2, .Lfill_regs, \sfx + .endif + INVOKE_STUB_LOAD_REG .Lload8i2, a2, s3, 8, ld, t3, .Lload4i3, t4, .Lload8i3, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload8i3, a3, s3, 8, ld, t3, .Lload4i4, t4, .Lload8i4, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload8i4, a4, s3, 8, ld, t3, .Lload4i5, t4, .Lload8i5, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload8i5, a5, s3, 8, ld, t3, .Lload4i6, t4, .Lload8i6, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload8i6, a6, s3, 8, ld, t3, .Lload4i7, t4, .Lload8i7, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload8i7, a7, s3, 8, ld, t3, .Lskip4, t4, .Lskip8, .Lfill_regs, \sfx + +// Handlers for loading floats into FPRs. + INVOKE_STUB_LOAD_REG .Lload4f0, fa0, s3, 4, flw, t5, .Lload4f1, t6, .Lload8f1, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload4f1, fa1, s3, 4, flw, t5, .Lload4f2, t6, .Lload8f2, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload4f2, fa2, s3, 4, flw, t5, .Lload4f3, t6, .Lload8f3, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload4f3, fa3, s3, 4, flw, t5, .Lload4f4, t6, .Lload8f4, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload4f4, fa4, s3, 4, flw, t5, .Lload4f5, t6, .Lload8f5, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload4f5, fa5, s3, 4, flw, t5, .Lload4f6, t6, .Lload8f6, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload4f6, fa6, s3, 4, flw, t5, .Lload4f7, t6, .Lload8f7, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload4f7, fa7, s3, 4, flw, t5, .Lskip4, t6, .Lskip8, .Lfill_regs, \sfx + +// Handlers for loading doubles into FPRs. + INVOKE_STUB_LOAD_REG .Lload8f0, fa0, s3, 8, fld, t5, .Lload4f1, t6, .Lload8f1, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload8f1, fa1, s3, 8, fld, t5, .Lload4f2, t6, .Lload8f2, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload8f2, fa2, s3, 8, fld, t5, .Lload4f3, t6, .Lload8f3, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload8f3, fa3, s3, 8, fld, t5, .Lload4f4, t6, .Lload8f4, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload8f4, fa4, s3, 8, fld, t5, .Lload4f5, t6, .Lload8f5, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload8f5, fa5, s3, 8, fld, t5, .Lload4f6, t6, .Lload8f6, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload8f6, fa6, s3, 8, fld, t5, .Lload4f7, t6, .Lload8f7, .Lfill_regs, \sfx + INVOKE_STUB_LOAD_REG .Lload8f7, fa7, s3, 8, fld, t5, .Lskip4, t6, .Lskip8, .Lfill_regs, \sfx + +// Handlers for skipping arguments that do not fit into registers. + INVOKE_STUB_SKIP_ARG .Lskip4, s3, 4, .Lfill_regs, \sfx + INVOKE_STUB_SKIP_ARG .Lskip8, s3, 8, .Lfill_regs, \sfx + +.Lcall_method\sfx: .endm @@ -268,49 +275,10 @@ END art_deliver_pending_exception ENTRY art_quick_invoke_stub INVOKE_STUB_CREATE_FRAME - lw a1, (s3) // Load `this`. - addi s3, s3, 4 // Increment argument pointer. - - INVOKE_STUB_LOOP 6 /* max GPRs available: a0 is for ArtMethod*, a1 is for `this` */ \ - .LstoreA4_1 .LstoreA8_1 .LstoreF4_1 .LstoreF8_1 .LfillRegisters1 .LcallFunction1 - -.LstoreA4_1: - LOADREG_I4 s4 a2 .LfillRegisters1 - LOADREG_I4 s4 a3 .LfillRegisters1 - LOADREG_I4 s4 a4 .LfillRegisters1 - LOADREG_I4 s4 a5 .LfillRegisters1 - LOADREG_I4 s4 a6 .LfillRegisters1 - LOADREG_I4 s4 a7 .LfillRegisters1 - -.LstoreA8_1: - LOADREG_I8 s4 a2 .LfillRegisters1 - LOADREG_I8 s4 a3 .LfillRegisters1 - LOADREG_I8 s4 a4 .LfillRegisters1 - LOADREG_I8 s4 a5 .LfillRegisters1 - LOADREG_I8 s4 a6 .LfillRegisters1 - LOADREG_I8 s4 a7 .LfillRegisters1 - -.LstoreF4_1: - LOADREG_F4 s5 fa0 .LfillRegisters1 - LOADREG_F4 s5 fa1 .LfillRegisters1 - LOADREG_F4 s5 fa2 .LfillRegisters1 - LOADREG_F4 s5 fa3 .LfillRegisters1 - LOADREG_F4 s5 fa4 .LfillRegisters1 - LOADREG_F4 s5 fa5 .LfillRegisters1 - LOADREG_F4 s5 fa6 .LfillRegisters1 - LOADREG_F4 s5 fa7 .LfillRegisters1 - -.LstoreF8_1: - LOADREG_F8 s5 fa0 .LfillRegisters1 - LOADREG_F8 s5 fa1 .LfillRegisters1 - LOADREG_F8 s5 fa2 .LfillRegisters1 - LOADREG_F8 s5 fa3 .LfillRegisters1 - LOADREG_F8 s5 fa4 .LfillRegisters1 - LOADREG_F8 s5 fa5 .LfillRegisters1 - LOADREG_F8 s5 fa6 .LfillRegisters1 - LOADREG_F8 s5 fa7 .LfillRegisters1 - -.LcallFunction1: + // Load args into registers. + INVOKE_STUB_LOAD_ALL_ARGS _instance + + // Call the method and return. INVOKE_STUB_CALL_AND_RETURN END art_quick_invoke_stub @@ -324,50 +292,10 @@ END art_quick_invoke_stub ENTRY art_quick_invoke_static_stub INVOKE_STUB_CREATE_FRAME - // The only difference with art_quick_invoke_stub is the absence of `this` in a1. - - INVOKE_STUB_LOOP 7 /* max GPRs available: a0 is for ArtMethod* */ \ - .LstoreA4_2 .LstoreA8_2 .LstoreF4_2 .LstoreF8_2 .LfillRegisters2 .LcallFunction2 - -.LstoreA4_2: - LOADREG_I4 s4 a1 .LfillRegisters2 - LOADREG_I4 s4 a2 .LfillRegisters2 - LOADREG_I4 s4 a3 .LfillRegisters2 - LOADREG_I4 s4 a4 .LfillRegisters2 - LOADREG_I4 s4 a5 .LfillRegisters2 - LOADREG_I4 s4 a6 .LfillRegisters2 - LOADREG_I4 s4 a7 .LfillRegisters2 - -.LstoreA8_2: - LOADREG_I8 s4 a1 .LfillRegisters2 - LOADREG_I8 s4 a2 .LfillRegisters2 - LOADREG_I8 s4 a3 .LfillRegisters2 - LOADREG_I8 s4 a4 .LfillRegisters2 - LOADREG_I8 s4 a5 .LfillRegisters2 - LOADREG_I8 s4 a6 .LfillRegisters2 - LOADREG_I8 s4 a7 .LfillRegisters2 - -.LstoreF4_2: - LOADREG_F4 s5 fa0 .LfillRegisters2 - LOADREG_F4 s5 fa1 .LfillRegisters2 - LOADREG_F4 s5 fa2 .LfillRegisters2 - LOADREG_F4 s5 fa3 .LfillRegisters2 - LOADREG_F4 s5 fa4 .LfillRegisters2 - LOADREG_F4 s5 fa5 .LfillRegisters2 - LOADREG_F4 s5 fa6 .LfillRegisters2 - LOADREG_F4 s5 fa7 .LfillRegisters2 - -.LstoreF8_2: - LOADREG_F8 s5 fa0 .LfillRegisters2 - LOADREG_F8 s5 fa1 .LfillRegisters2 - LOADREG_F8 s5 fa2 .LfillRegisters2 - LOADREG_F8 s5 fa3 .LfillRegisters2 - LOADREG_F8 s5 fa4 .LfillRegisters2 - LOADREG_F8 s5 fa5 .LfillRegisters2 - LOADREG_F8 s5 fa6 .LfillRegisters2 - LOADREG_F8 s5 fa7 .LfillRegisters2 -.LcallFunction2: + // Load args into registers. + INVOKE_STUB_LOAD_ALL_ARGS _static + // Call the method and return. INVOKE_STUB_CALL_AND_RETURN END art_quick_invoke_static_stub |