summaryrefslogtreecommitdiff
path: root/include/sbi/riscv_asm.h
diff options
context:
space:
mode:
authorAnup Patel <anup.patel@wdc.com>2018-12-11 16:54:06 +0300
committerAnup Patel <anup@brainfault.org>2018-12-11 16:54:06 +0300
commit9e8ff05cb61f157fb0bcb6b0071d7b6dc0763faa (patch)
treeb9513a86b3b36e569cb46387846fee9c5544f566 /include/sbi/riscv_asm.h
downloadopensbi-9e8ff05cb61f157fb0bcb6b0071d7b6dc0763faa.tar.xz
Initial commit.
Signed-off-by: Anup Patel <anup.patel@wdc.com>
Diffstat (limited to 'include/sbi/riscv_asm.h')
-rw-r--r--include/sbi/riscv_asm.h244
1 files changed, 244 insertions, 0 deletions
diff --git a/include/sbi/riscv_asm.h b/include/sbi/riscv_asm.h
new file mode 100644
index 0000000..516bf6f
--- /dev/null
+++ b/include/sbi/riscv_asm.h
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2018 Western Digital Corporation or its affiliates.
+ *
+ * Authors:
+ * Anup Patel <anup.patel@wdc.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#ifndef __RISCV_ASM_H__
+#define __RISCV_ASM_H__
+
+#ifdef __ASSEMBLY__
+#define __ASM_STR(x) x
+#else
+#define __ASM_STR(x) #x
+#endif
+
+#if __riscv_xlen == 64
+#define __REG_SEL(a, b) __ASM_STR(a)
+#elif __riscv_xlen == 32
+#define __REG_SEL(a, b) __ASM_STR(b)
+#else
+#error "Unexpected __riscv_xlen"
+#endif
+
+#define REG_L __REG_SEL(ld, lw)
+#define REG_S __REG_SEL(sd, sw)
+#define SZREG __REG_SEL(8, 4)
+#define LGREG __REG_SEL(3, 2)
+
+#if __SIZEOF_POINTER__ == 8
+#ifdef __ASSEMBLY__
+#define RISCV_PTR .dword
+#define RISCV_SZPTR 8
+#define RISCV_LGPTR 3
+#else
+#define RISCV_PTR ".dword"
+#define RISCV_SZPTR "8"
+#define RISCV_LGPTR "3"
+#endif
+#elif __SIZEOF_POINTER__ == 4
+#ifdef __ASSEMBLY__
+#define RISCV_PTR .word
+#define RISCV_SZPTR 4
+#define RISCV_LGPTR 2
+#else
+#define RISCV_PTR ".word"
+#define RISCV_SZPTR "4"
+#define RISCV_LGPTR "2"
+#endif
+#else
+#error "Unexpected __SIZEOF_POINTER__"
+#endif
+
+#if (__SIZEOF_INT__ == 4)
+#define RISCV_INT __ASM_STR(.word)
+#define RISCV_SZINT __ASM_STR(4)
+#define RISCV_LGINT __ASM_STR(2)
+#else
+#error "Unexpected __SIZEOF_INT__"
+#endif
+
+#if (__SIZEOF_SHORT__ == 2)
+#define RISCV_SHORT __ASM_STR(.half)
+#define RISCV_SZSHORT __ASM_STR(2)
+#define RISCV_LGSHORT __ASM_STR(1)
+#else
+#error "Unexpected __SIZEOF_SHORT__"
+#endif
+
+#define RISCV_SCRATCH_TMP0_OFFSET (0 * __SIZEOF_POINTER__)
+#define RISCV_SCRATCH_FW_START_OFFSET (1 * __SIZEOF_POINTER__)
+#define RISCV_SCRATCH_FW_SIZE_OFFSET (2 * __SIZEOF_POINTER__)
+#define RISCV_SCRATCH_NEXT_ARG1_OFFSET (3 * __SIZEOF_POINTER__)
+#define RISCV_SCRATCH_NEXT_ADDR_OFFSET (4 * __SIZEOF_POINTER__)
+#define RISCV_SCRATCH_NEXT_MODE_OFFSET (5 * __SIZEOF_POINTER__)
+#define RISCV_SCRATCH_WARMBOOT_ADDR_OFFSET (6 * __SIZEOF_POINTER__)
+#define RISCV_SCRATCH_PLATFORM_ADDR_OFFSET (7 * __SIZEOF_POINTER__)
+#define RISCV_SCRATCH_HARTID_TO_SCRATCH_OFFSET (8 * __SIZEOF_POINTER__)
+#define RISCV_SCRATCH_IPI_TYPE_OFFSET (9 * __SIZEOF_POINTER__)
+#define RISCV_SCRATCH_SIZE 256
+
+#define RISCV_TRAP_REGS_zero 0
+#define RISCV_TRAP_REGS_ra 1
+#define RISCV_TRAP_REGS_sp 2
+#define RISCV_TRAP_REGS_gp 3
+#define RISCV_TRAP_REGS_tp 4
+#define RISCV_TRAP_REGS_t0 5
+#define RISCV_TRAP_REGS_t1 6
+#define RISCV_TRAP_REGS_t2 7
+#define RISCV_TRAP_REGS_s0 8
+#define RISCV_TRAP_REGS_s1 9
+#define RISCV_TRAP_REGS_a0 10
+#define RISCV_TRAP_REGS_a1 11
+#define RISCV_TRAP_REGS_a2 12
+#define RISCV_TRAP_REGS_a3 13
+#define RISCV_TRAP_REGS_a4 14
+#define RISCV_TRAP_REGS_a5 15
+#define RISCV_TRAP_REGS_a6 16
+#define RISCV_TRAP_REGS_a7 17
+#define RISCV_TRAP_REGS_s2 18
+#define RISCV_TRAP_REGS_s3 19
+#define RISCV_TRAP_REGS_s4 20
+#define RISCV_TRAP_REGS_s5 21
+#define RISCV_TRAP_REGS_s6 22
+#define RISCV_TRAP_REGS_s7 23
+#define RISCV_TRAP_REGS_s8 24
+#define RISCV_TRAP_REGS_s9 25
+#define RISCV_TRAP_REGS_s10 26
+#define RISCV_TRAP_REGS_s11 27
+#define RISCV_TRAP_REGS_t3 28
+#define RISCV_TRAP_REGS_t4 29
+#define RISCV_TRAP_REGS_t5 30
+#define RISCV_TRAP_REGS_t6 31
+#define RISCV_TRAP_REGS_mepc 32
+#define RISCV_TRAP_REGS_mstatus 33
+#define RISCV_TRAP_REGS_last 34
+
+#define RISCV_TRAP_REGS_OFFSET(x) \
+ ((RISCV_TRAP_REGS_##x) * __SIZEOF_POINTER__)
+#define RISCV_TRAP_REGS_SIZE RISCV_TRAP_REGS_OFFSET(last)
+
+#ifndef __ASSEMBLY__
+
+#define csr_swap(csr, val) \
+({ \
+ unsigned long __v = (unsigned long)(val); \
+ __asm__ __volatile__ ("csrrw %0, " #csr ", %1" \
+ : "=r" (__v) : "rK" (__v) \
+ : "memory"); \
+ __v; \
+})
+
+#define csr_read(csr) \
+({ \
+ register unsigned long __v; \
+ __asm__ __volatile__ ("csrr %0, " #csr \
+ : "=r" (__v) : \
+ : "memory"); \
+ __v; \
+})
+
+#define csr_read_n(csr_num) \
+({ \
+ register unsigned long __v; \
+ __asm__ __volatile__ ("csrr %0, " __ASM_STR(csr_num) \
+ : "=r" (__v) : \
+ : "memory"); \
+ __v; \
+})
+
+#define csr_write(csr, val) \
+({ \
+ unsigned long __v = (unsigned long)(val); \
+ __asm__ __volatile__ ("csrw " #csr ", %0" \
+ : : "rK" (__v) \
+ : "memory"); \
+})
+
+#define csr_write_n(csr_num, val) \
+({ \
+ unsigned long __v = (unsigned long)(val); \
+ __asm__ __volatile__ ("csrw " __ASM_STR(csr_num) ", %0" \
+ : : "rK" (__v) \
+ : "memory"); \
+})
+
+#define csr_read_set(csr, val) \
+({ \
+ unsigned long __v = (unsigned long)(val); \
+ __asm__ __volatile__ ("csrrs %0, " #csr ", %1" \
+ : "=r" (__v) : "rK" (__v) \
+ : "memory"); \
+ __v; \
+})
+
+#define csr_set(csr, val) \
+({ \
+ unsigned long __v = (unsigned long)(val); \
+ __asm__ __volatile__ ("csrs " #csr ", %0" \
+ : : "rK" (__v) \
+ : "memory"); \
+})
+
+#define csr_read_clear(csr, val) \
+({ \
+ unsigned long __v = (unsigned long)(val); \
+ __asm__ __volatile__ ("csrrc %0, " #csr ", %1" \
+ : "=r" (__v) : "rK" (__v) \
+ : "memory"); \
+ __v; \
+})
+
+#define csr_clear(csr, val) \
+({ \
+ unsigned long __v = (unsigned long)(val); \
+ __asm__ __volatile__ ("csrc " #csr ", %0" \
+ : : "rK" (__v) \
+ : "memory"); \
+})
+
+unsigned long csr_read_num(int csr_num);
+
+void csr_write_num(int csr_num, unsigned long val);
+
+#define wfi() \
+do { \
+ __asm__ __volatile__ ("wfi" ::: "memory"); \
+} while (0)
+
+static inline int misa_extension(char ext)
+{
+ return csr_read(misa) & (1 << (ext - 'A'));
+}
+
+static inline int misa_xlen(void)
+{
+ return ((long)csr_read(misa) < 0) ? 64 : 32;
+}
+
+static inline void misa_string(char *out, unsigned int out_sz)
+{
+ unsigned long i, val = csr_read(misa);
+
+ for (i = 0; i < 26; i++) {
+ if (val & (1 << i)) {
+ *out = 'A' + i;
+ out++;
+ }
+ }
+ *out = '\0';
+ out++;
+}
+
+int pmp_set(unsigned int n, unsigned long prot,
+ unsigned long addr, unsigned long log2len);
+
+int pmp_get(unsigned int n, unsigned long *prot_out,
+ unsigned long *addr_out, unsigned long *log2len_out);
+
+#endif /* !__ASSEMBLY__ */
+
+#endif