invokeNative_riscv.S 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * Copyright (C) 2019 Intel Corporation. All rights reserved.
  3. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. */
  5. /*
  6. * The float abi macros used bellow are from risc-v c api:
  7. * https://github.com/riscv/riscv-c-api-doc/blob/master/riscv-c-api.md
  8. *
  9. */
  10. #if defined(__riscv_float_abi_soft)
  11. #define RV_FPREG_SIZE 0
  12. #elif defined(__riscv_float_abi_single)
  13. #define RV_OP_LOADFPREG flw
  14. #define RV_OP_STROEFPREG fsw
  15. #define RV_FPREG_SIZE 4
  16. #elif defined(__riscv_float_abi_double)
  17. #define RV_OP_LOADFPREG fld
  18. #define RV_OP_STROEFPREG fsd
  19. #define RV_FPREG_SIZE 8
  20. #endif
  21. #if __riscv_xlen == 32
  22. #define RV_OP_LOADREG lw
  23. #define RV_OP_STOREREG sw
  24. #define RV_REG_SIZE 4
  25. #define RV_REG_SHIFT 2
  26. #define RV_FP_OFFSET (8 * RV_REG_SIZE)
  27. #define RV_INT_OFFSET 0
  28. #else
  29. #define RV_OP_LOADREG ld
  30. #define RV_OP_STOREREG sd
  31. #define RV_REG_SIZE 8
  32. #define RV_REG_SHIFT 3
  33. #define RV_FP_OFFSET 0
  34. #define RV_INT_OFFSET (8 * RV_FPREG_SIZE)
  35. #endif
  36. .text
  37. .align 2
  38. #ifndef BH_PLATFORM_DARWIN
  39. .globl invokeNative
  40. .type invokeNative, function
  41. invokeNative:
  42. #else
  43. .globl _invokeNative
  44. _invokeNative:
  45. #endif /* end of BH_PLATFORM_DARWIN */
  46. /*
  47. * Arguments passed in:
  48. *
  49. * a0 function ptr
  50. * a1 argv
  51. * a2 nstacks
  52. */
  53. /*
  54. * sp (stack pointer)
  55. * |- sd/sw to store 64/32-bit values from register to memory
  56. * |- ld/lw to load from stack to register
  57. * fp/s0 (frame pointer)
  58. * a0-a7 (8 integer arguments)
  59. * |- sd/sw to store
  60. * |- ld/lw to load
  61. * fa0-a7 (8 float arguments)
  62. * |- fsd/fsw to store
  63. * |- fld/fsw to load
  64. * t0-t6 (temporaries regisgers)
  65. * |- caller saved
  66. */
  67. /* reserve space on stack to save return address and frame pointer */
  68. addi sp, sp, - 2 * RV_REG_SIZE
  69. RV_OP_STOREREG fp, 0 * RV_REG_SIZE(sp) /* save frame pointer */
  70. RV_OP_STOREREG ra, 1 * RV_REG_SIZE(sp) /* save return address */
  71. mv fp, sp /* set frame pointer to bottom of fixed frame */
  72. /* save function ptr, argv & nstacks */
  73. mv t0, a0 /* t0 = function ptr */
  74. mv t1, a1 /* t1 = argv array address */
  75. mv t2, a2 /* t2 = nstack */
  76. #ifndef __riscv_float_abi_soft
  77. /* fill in fa0-7 float-registers*/
  78. RV_OP_LOADFPREG fa0, RV_FP_OFFSET + 0 * RV_FPREG_SIZE(t1) /* fa0 */
  79. RV_OP_LOADFPREG fa1, RV_FP_OFFSET + 1 * RV_FPREG_SIZE(t1) /* fa1 */
  80. RV_OP_LOADFPREG fa2, RV_FP_OFFSET + 2 * RV_FPREG_SIZE(t1) /* fa2 */
  81. RV_OP_LOADFPREG fa3, RV_FP_OFFSET + 3 * RV_FPREG_SIZE(t1) /* fa3 */
  82. RV_OP_LOADFPREG fa4, RV_FP_OFFSET + 4 * RV_FPREG_SIZE(t1) /* fa4 */
  83. RV_OP_LOADFPREG fa5, RV_FP_OFFSET + 5 * RV_FPREG_SIZE(t1) /* fa5 */
  84. RV_OP_LOADFPREG fa6, RV_FP_OFFSET + 6 * RV_FPREG_SIZE(t1) /* fa6 */
  85. RV_OP_LOADFPREG fa7, RV_FP_OFFSET + 7 * RV_FPREG_SIZE(t1) /* fa7 */
  86. #endif
  87. /* fill in a0-7 integer-registers*/
  88. RV_OP_LOADREG a0, RV_INT_OFFSET + 0 * RV_REG_SIZE(t1) /* a0 */
  89. RV_OP_LOADREG a1, RV_INT_OFFSET + 1 * RV_REG_SIZE(t1) /* a1 */
  90. RV_OP_LOADREG a2, RV_INT_OFFSET + 2 * RV_REG_SIZE(t1) /* a2 */
  91. RV_OP_LOADREG a3, RV_INT_OFFSET + 3 * RV_REG_SIZE(t1) /* a3 */
  92. RV_OP_LOADREG a4, RV_INT_OFFSET + 4 * RV_REG_SIZE(t1) /* a4 */
  93. RV_OP_LOADREG a5, RV_INT_OFFSET + 5 * RV_REG_SIZE(t1) /* a5 */
  94. RV_OP_LOADREG a6, RV_INT_OFFSET + 6 * RV_REG_SIZE(t1) /* a6 */
  95. RV_OP_LOADREG a7, RV_INT_OFFSET + 7 * RV_REG_SIZE(t1) /* a7 */
  96. /* t1 points to stack args */
  97. /* RV_FPREG_SIZE is zero when __riscv_float_abi_soft defined */
  98. addi t1, t1, RV_REG_SIZE * 8 + RV_FPREG_SIZE * 8
  99. /* directly call the function if no args in stack,
  100. x0 always holds 0 */
  101. beq t2, x0, call_func
  102. /* reserve enough stack space for function arguments */
  103. sll t3, t2, RV_REG_SHIFT /* shift left 3 bits. t3 = n_stacks * 8 */
  104. sub sp, sp, t3
  105. /* make 16-byte aligned */
  106. li t3, 15
  107. not t3, t3
  108. and sp, sp, t3
  109. /* save sp in t4 register */
  110. mv t4, sp
  111. /* copy left arguments from caller stack to own frame stack */
  112. loop_stack_args:
  113. beq t2, x0, call_func
  114. RV_OP_LOADREG t5, 0(t1) /* load stack argument, t5 = argv[i] */
  115. RV_OP_STOREREG t5, 0(t4) /* store t5 to reseved stack, sp[j] = t5 */
  116. addi t1, t1, RV_REG_SIZE /* move to next stack argument */
  117. addi t4, t4, RV_REG_SIZE /* move to next stack pointer */
  118. addi t2, t2, -1 /* decrease t2 every loop, nstacks = nstacks -1 */
  119. j loop_stack_args
  120. call_func:
  121. jalr t0
  122. /* restore registers pushed in stack or saved in another register */
  123. return:
  124. mv sp, fp /* restore sp saved in fp before function call */
  125. RV_OP_LOADREG fp, 0 * RV_REG_SIZE(sp) /* load previous frame poniter to fp register */
  126. RV_OP_LOADREG ra, 1 * RV_REG_SIZE(sp) /* load previous return address to ra register */
  127. addi sp, sp, 2 * RV_REG_SIZE /* pop frame, restore sp */
  128. jr ra