1/*
2 * Copyright (c) 2017 Jean-Paul Etienne <fractalclone@gmail.com>
3 * Contributors: 2018 Antmicro <www.antmicro.com>
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8#include <zephyr/toolchain.h>
9
10/* exports */
11GTEXT(__start)
12
13/* imports */
14GTEXT(__initialize)
15#if defined(CONFIG_GEN_SW_ISR_TABLE)
16GTEXT(_isr_wrapper)
17#endif
18
19SECTION_FUNC(vectors, __start)
20#if defined(CONFIG_RISCV_GP)
21	/* Initialize global pointer */
22	.option push
23	.option norelax
24	la gp, __global_pointer$
25	.option pop
26#endif
27
28	.option norvc;
29
30#if defined(CONFIG_RISCV_VECTORED_MODE)
31#if defined(CONFIG_RISCV_HAS_CLIC)
32
33	/*
34	 * CLIC vectored mode
35	 *
36	 * CLIC vectored mode uses mtvec exclusively for exception handling and
37	 * mtvec.base must be aligned to 64 bytes (this is done using
38	 * CONFIG_RISCV_TRAP_HANDLER_ALIGNMENT)
39	 */
40#if defined(CONFIG_GEN_SW_ISR_TABLE)
41	la t0, _isr_wrapper
42#else
43	add t0, zero, zero
44#endif
45	addi t0, t0, 0x03 /* Enable CLIC vectored mode by setting LSB */
46	csrw mtvec, t0
47
48	/*
49	 * CLIC vectored mode has a similar concept to CLINT vectored mode,
50	 * where an interrupt vector table is used for specific interrupts.
51	 * However, in CLIC vectored mode, the handler table contains the
52	 * address of the interrupt handler instead of an opcode containing a
53	 * jump instruction, this is done by leveraging
54	 * CONFIG_IRQ_VECTOR_TABLE_JUMP_BY_ADDRESS.
55	 * When an interrupt occurs in CLIC vectored mode, the address of the
56	 * handler entry from the vector table is loaded and then jumped to in
57	 * hardware. This time mtvt is used as the base address for the
58	 * interrupt table.
59	 */
60	la t0, _irq_vector_table
61	csrw 0x307, t0 /* mtvt */
62
63#else /* !CONFIG_RISCV_HAS_CLIC */
64
65	/*
66	 * CLINT vectored mode
67	 *
68	 * Set mtvec (Machine Trap-Vector Base-Address Register)
69	 * to _irq_vector_table (interrupt vector table). Add 1 to base
70	 * address of _irq_vector_table to indicate that vectored mode
71	 * is used (LSB = 0x1). CPU will mask the LSB out of
72	 * the address so that base address of _irq_vector_table is used.
73	 *
74	 * NOTE: _irq_vector_table is 256-byte aligned. Incorrect alignment
75	 *        of _irq_vector_table breaks this code.
76	 */
77	la t0, _irq_vector_table /* Load address of interrupt vector table */
78	addi t0, t0, 0x01 /* Enable vectored mode by setting LSB */
79	csrw mtvec, t0
80
81#endif /* CONFIG_RISCV_HAS_CLIC */
82
83#else /* !CONFIG_RISCV_VECTORED_MODE */
84
85#if defined(CONFIG_RISCV_HAS_CLIC) && !defined(CONFIG_LEGACY_CLIC)
86
87	la t0, _isr_wrapper
88	addi t0, t0, 0x03 /* Set mode bits to 3, signifying CLIC. Everything else is reserved. */
89	csrw mtvec, t0
90
91#else /* !CONFIG_RISCV_HAS_CLIC || CONFIG_LEGACY_CLIC */
92
93	/*
94	 * CLINT direct mode
95	 *
96	 * Set mtvec (Machine Trap-Vector Base-Address Register)
97	 * to _isr_wrapper.
98	 */
99	la t0, _isr_wrapper
100	csrw mtvec, t0
101
102#endif /* CONFIG_RISCV_HAS_CLIC&& !CONFIG_LEGACY_CLIC */
103
104#endif /* CONFIG_RISCV_VECTORED_MODE */
105
106	/* Jump to __reset */
107	tail __reset
108