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