riscv_asm.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /*
  2. * SPDX-License-Identifier: BSD-2-Clause
  3. *
  4. * Copyright (c) 2019 Western Digital Corporation or its affiliates.
  5. *
  6. * Authors:
  7. * Anup Patel <anup.patel@wdc.com>
  8. */
  9. #ifndef __RISCV_ASM_H__
  10. #define __RISCV_ASM_H__
  11. #include <sbi/riscv_encoding.h>
  12. /* clang-format off */
  13. #ifdef __ASSEMBLY__
  14. #define __ASM_STR(x) x
  15. #else
  16. #define __ASM_STR(x) #x
  17. #endif
  18. #if __riscv_xlen == 64
  19. #define __REG_SEL(a, b) __ASM_STR(a)
  20. #elif __riscv_xlen == 32
  21. #define __REG_SEL(a, b) __ASM_STR(b)
  22. #else
  23. #error "Unexpected __riscv_xlen"
  24. #endif
  25. #define PAGE_SHIFT (12)
  26. #define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
  27. #define PAGE_MASK (~(PAGE_SIZE - 1))
  28. #define SBI_TLB_FLUSH_ALL ((unsigned long)-1)
  29. #define REG_L __REG_SEL(ld, lw)
  30. #define REG_S __REG_SEL(sd, sw)
  31. #define SZREG __REG_SEL(8, 4)
  32. #define LGREG __REG_SEL(3, 2)
  33. #if __SIZEOF_POINTER__ == 8
  34. #define BITS_PER_LONG 64
  35. #ifdef __ASSEMBLY__
  36. #define RISCV_PTR .dword
  37. #define RISCV_SZPTR 8
  38. #define RISCV_LGPTR 3
  39. #else
  40. #define RISCV_PTR ".dword"
  41. #define RISCV_SZPTR "8"
  42. #define RISCV_LGPTR "3"
  43. #endif
  44. #elif __SIZEOF_POINTER__ == 4
  45. #define BITS_PER_LONG 32
  46. #ifdef __ASSEMBLY__
  47. #define RISCV_PTR .word
  48. #define RISCV_SZPTR 4
  49. #define RISCV_LGPTR 2
  50. #else
  51. #define RISCV_PTR ".word"
  52. #define RISCV_SZPTR "4"
  53. #define RISCV_LGPTR "2"
  54. #endif
  55. #else
  56. #error "Unexpected __SIZEOF_POINTER__"
  57. #endif
  58. #if (__SIZEOF_INT__ == 4)
  59. #define RISCV_INT __ASM_STR(.word)
  60. #define RISCV_SZINT __ASM_STR(4)
  61. #define RISCV_LGINT __ASM_STR(2)
  62. #else
  63. #error "Unexpected __SIZEOF_INT__"
  64. #endif
  65. #if (__SIZEOF_SHORT__ == 2)
  66. #define RISCV_SHORT __ASM_STR(.half)
  67. #define RISCV_SZSHORT __ASM_STR(2)
  68. #define RISCV_LGSHORT __ASM_STR(1)
  69. #else
  70. #error "Unexpected __SIZEOF_SHORT__"
  71. #endif
  72. /* clang-format on */
  73. #ifndef __ASSEMBLY__
  74. #define csr_swap(csr, val) \
  75. ({ \
  76. unsigned long __v = (unsigned long)(val); \
  77. __asm__ __volatile__("csrrw %0, " __ASM_STR(csr) ", %1" \
  78. : "=r"(__v) \
  79. : "rK"(__v) \
  80. : "memory"); \
  81. __v; \
  82. })
  83. #define csr_read(csr) \
  84. ({ \
  85. register unsigned long __v; \
  86. __asm__ __volatile__("csrr %0, " __ASM_STR(csr) \
  87. : "=r"(__v) \
  88. : \
  89. : "memory"); \
  90. __v; \
  91. })
  92. #define csr_write(csr, val) \
  93. ({ \
  94. unsigned long __v = (unsigned long)(val); \
  95. __asm__ __volatile__("csrw " __ASM_STR(csr) ", %0" \
  96. : \
  97. : "rK"(__v) \
  98. : "memory"); \
  99. })
  100. #define csr_read_set(csr, val) \
  101. ({ \
  102. unsigned long __v = (unsigned long)(val); \
  103. __asm__ __volatile__("csrrs %0, " __ASM_STR(csr) ", %1" \
  104. : "=r"(__v) \
  105. : "rK"(__v) \
  106. : "memory"); \
  107. __v; \
  108. })
  109. #define csr_set(csr, val) \
  110. ({ \
  111. unsigned long __v = (unsigned long)(val); \
  112. __asm__ __volatile__("csrs " __ASM_STR(csr) ", %0" \
  113. : \
  114. : "rK"(__v) \
  115. : "memory"); \
  116. })
  117. #define csr_read_clear(csr, val) \
  118. ({ \
  119. unsigned long __v = (unsigned long)(val); \
  120. __asm__ __volatile__("csrrc %0, " __ASM_STR(csr) ", %1" \
  121. : "=r"(__v) \
  122. : "rK"(__v) \
  123. : "memory"); \
  124. __v; \
  125. })
  126. #define csr_clear(csr, val) \
  127. ({ \
  128. unsigned long __v = (unsigned long)(val); \
  129. __asm__ __volatile__("csrc " __ASM_STR(csr) ", %0" \
  130. : \
  131. : "rK"(__v) \
  132. : "memory"); \
  133. })
  134. unsigned long csr_read_num(int csr_num);
  135. void csr_write_num(int csr_num, unsigned long val);
  136. #define wfi() \
  137. do { \
  138. __asm__ __volatile__("wfi" ::: "memory"); \
  139. } while (0)
  140. static inline int misa_extension(char ext)
  141. {
  142. return csr_read(CSR_MISA) & (1 << (ext - 'A'));
  143. }
  144. static inline int misa_xlen(void)
  145. {
  146. return ((long)csr_read(CSR_MISA) < 0) ? 64 : 32;
  147. }
  148. static inline void misa_string(char *out, unsigned int out_sz)
  149. {
  150. unsigned long i, val = csr_read(CSR_MISA);
  151. for (i = 0; i < 26; i++) {
  152. if (val & (1 << i)) {
  153. *out = 'A' + i;
  154. out++;
  155. }
  156. }
  157. *out = '\0';
  158. out++;
  159. }
  160. int pmp_set(unsigned int n, unsigned long prot, unsigned long addr,
  161. unsigned long log2len);
  162. int pmp_get(unsigned int n, unsigned long *prot_out, unsigned long *addr_out,
  163. unsigned long *log2len_out);
  164. #endif /* !__ASSEMBLY__ */
  165. #endif