195 lines
5.4 KiB
C
195 lines
5.4 KiB
C
|
/*
|
||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||
|
*
|
||
|
* Copyright (c) 2019 Western Digital Corporation or its affiliates.
|
||
|
*
|
||
|
* Authors:
|
||
|
* Anup Patel <anup.patel@wdc.com>
|
||
|
*/
|
||
|
|
||
|
#ifndef __RISCV_ASM_H__
|
||
|
#define __RISCV_ASM_H__
|
||
|
|
||
|
#include <sbi/riscv_encoding.h>
|
||
|
|
||
|
/* clang-format off */
|
||
|
|
||
|
#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 PAGE_SHIFT (12)
|
||
|
#define PAGE_SIZE (_AC(1, UL) << PAGE_SHIFT)
|
||
|
#define PAGE_MASK (~(PAGE_SIZE - 1))
|
||
|
|
||
|
#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
|
||
|
#define BITS_PER_LONG 64
|
||
|
#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
|
||
|
#define BITS_PER_LONG 32
|
||
|
#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
|
||
|
|
||
|
/* clang-format on */
|
||
|
|
||
|
#ifndef __ASSEMBLY__
|
||
|
|
||
|
#define csr_swap(csr, val) \
|
||
|
({ \
|
||
|
unsigned long __v = (unsigned long)(val); \
|
||
|
__asm__ __volatile__("csrrw %0, " __ASM_STR(csr) ", %1" \
|
||
|
: "=r"(__v) \
|
||
|
: "rK"(__v) \
|
||
|
: "memory"); \
|
||
|
__v; \
|
||
|
})
|
||
|
|
||
|
#define csr_read(csr) \
|
||
|
({ \
|
||
|
register unsigned long __v; \
|
||
|
__asm__ __volatile__("csrr %0, " __ASM_STR(csr) \
|
||
|
: "=r"(__v) \
|
||
|
: \
|
||
|
: "memory"); \
|
||
|
__v; \
|
||
|
})
|
||
|
|
||
|
#define csr_write(csr, val) \
|
||
|
({ \
|
||
|
unsigned long __v = (unsigned long)(val); \
|
||
|
__asm__ __volatile__("csrw " __ASM_STR(csr) ", %0" \
|
||
|
: \
|
||
|
: "rK"(__v) \
|
||
|
: "memory"); \
|
||
|
})
|
||
|
|
||
|
#define csr_read_set(csr, val) \
|
||
|
({ \
|
||
|
unsigned long __v = (unsigned long)(val); \
|
||
|
__asm__ __volatile__("csrrs %0, " __ASM_STR(csr) ", %1" \
|
||
|
: "=r"(__v) \
|
||
|
: "rK"(__v) \
|
||
|
: "memory"); \
|
||
|
__v; \
|
||
|
})
|
||
|
|
||
|
#define csr_set(csr, val) \
|
||
|
({ \
|
||
|
unsigned long __v = (unsigned long)(val); \
|
||
|
__asm__ __volatile__("csrs " __ASM_STR(csr) ", %0" \
|
||
|
: \
|
||
|
: "rK"(__v) \
|
||
|
: "memory"); \
|
||
|
})
|
||
|
|
||
|
#define csr_read_clear(csr, val) \
|
||
|
({ \
|
||
|
unsigned long __v = (unsigned long)(val); \
|
||
|
__asm__ __volatile__("csrrc %0, " __ASM_STR(csr) ", %1" \
|
||
|
: "=r"(__v) \
|
||
|
: "rK"(__v) \
|
||
|
: "memory"); \
|
||
|
__v; \
|
||
|
})
|
||
|
|
||
|
#define csr_clear(csr, val) \
|
||
|
({ \
|
||
|
unsigned long __v = (unsigned long)(val); \
|
||
|
__asm__ __volatile__("csrc " __ASM_STR(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(CSR_MISA) & (1 << (ext - 'A'));
|
||
|
}
|
||
|
|
||
|
static inline int misa_xlen(void)
|
||
|
{
|
||
|
return ((long)csr_read(CSR_MISA) < 0) ? 64 : 32;
|
||
|
}
|
||
|
|
||
|
static inline void misa_string(char *out, unsigned int out_sz)
|
||
|
{
|
||
|
unsigned long i, val = csr_read(CSR_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
|