1/* 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright © 2019 Keith Packard 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 13 * 2. Redistributions in binary form must reproduce the above 14 * copyright notice, this list of conditions and the following 15 * disclaimer in the documentation and/or other materials provided 16 * with the distribution. 17 * 18 * 3. Neither the name of the copyright holder nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 27 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 29 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 32 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 33 * OF THE POSSIBILITY OF SUCH DAMAGE. 34 */ 35 36#include <picolibc.h> 37 38#define SPARC_NWIN 8 39 40#define PSR_VER_BIT 24 41#define PSR_PIL_BIT 8 42 43#define PSR_VER (0xf << PSR_VER_BIT) 44#define PSR_EF (1 << 12) 45#define PSR_S (1 << 7) 46#define PSR_PS (1 << 6) 47#define PSR_ET (1 << 5) 48#define PSR_PIL (0xf << PSR_PIL_BIT) 49#define PSR_CWP 0x1f 50 51#define TRAP(func) \ 52 rd %psr, %l0 ; \ 53 sethi %hi(_sparc_ ## func ## _isr), %l4 ;\ 54 jmp %l4+%lo(_sparc_ ## func ## _isr) ;\ 55 rd %tbr, %l6 ; 56 57#define TRAP_IN_TRAP \ 58 ta 0x00 ; \ 59 nop ; \ 60 nop ; \ 61 nop ; 62 63#define TRAP_HALT(name) \ 64 TRAP(name) ; \ 65 .weak _sparc_ ## name ## _isr ; \ 66 .equ _sparc_ ## name ## _isr, _sparc_halt_isr ; 67 68 .section .data.init.enter 69 .globl __weak_interrupt_vector 70__weak_interrupt_vector: 71 TRAP(reset) 72 TRAP_HALT(instruction_access_exception) 73 TRAP_HALT(illegal_instruction) 74 TRAP_HALT(priveledged_instruction) 75 TRAP_HALT(fp_disabled) 76#ifdef _FLAT 77 TRAP_HALT(window_overflow) 78 TRAP_HALT(window_underflow) 79#else 80 TRAP(window_overflow) 81 TRAP(window_underflow) 82#endif 83 TRAP_HALT(mem_address_not_aligned) 84 TRAP_HALT(fp_exception) 85 TRAP_HALT(data_access_exception) 86 TRAP_HALT(tag_overflow) 87 TRAP_HALT(watchpoint_detected) 88 TRAP_HALT(trap_0c) 89 TRAP_HALT(trap_0d) 90 TRAP_HALT(trap_0e) 91 TRAP_HALT(trap_0f) 92 TRAP_HALT(trap_10) 93 94 . = __weak_interrupt_vector + 0x80 * 16 95 96 TRAP_HALT(syscall) 97 TRAP_HALT(breakpoint) 98 TRAP_HALT(divide_by_zero) 99#ifdef _FLAT 100 TRAP_HALT(window_flush) 101#else 102 TRAP(window_flush) 103#endif 104 TRAP_HALT(clean_windows) 105 .size __weak_interrupt_vector, . - __weak_interrupt_vector 106 .weak __interrupt_vector 107 .equ __interrupt_vector, __weak_interrupt_vector 108 109 .text 110 .align 4 111 112 .global _sparc_reset_isr 113 .type _sparc_reset_isr, #function 114_sparc_reset_isr: 115 sethi %hi(_start), %g4 116 jmp %g4+%lo(_start) 117 nop 118 .size _sparc_reset_isr, .-_sparc_reset_isr 119 120 .global _sparc_halt_isr 121 .type _sparc_halt_isr, #function 122_sparc_halt_isr: 123 ta 0x00 124 ba _sparc_halt_isr 125 nop 126 .size _sparc_halt_isr, .-_sparc_halt_isr 127 128 .global _sparc_window_overflow_isr 129 .type _sparc_window_overflow_isr, #function 130_sparc_window_overflow_isr: 131 /* Enter the window to be stored. */ 132 save 133 /* Save local register set. */ 134 std %l0, [%sp + 0x00] 135 std %l2, [%sp + 0x08] 136 std %l4, [%sp + 0x10] 137 rd %wim, %l3 138 std %l6, [%sp + 0x18] 139 /* l2 := WIM << (NWIN-1) */ 140 sll %l3, (SPARC_NWIN-1), %l2 141 /* Save input register set. */ 142 std %i0, [%sp + 0x20] 143 /* l3 := WIM >> 1 */ 144 srl %l3, 1, %l3 145 std %i2, [%sp + 0x28] 146 /* WIM := (WIM >> 1) ^ (WIM << (NWIN-1)) */ 147 wr %l3, %l2, %wim 148 /* NOTE: 3 instruction before restore (delayed write instruction) */ 149 std %i4, [%sp + 0x30] 150 nop 151 std %i6, [%sp + 0x38] 152 /* Go back to trap window. */ 153 restore 154 /* Re-execute save. */ 155 jmp %l1 156 rett %l2 157 .size _sparc_window_overflow_isr, .-_sparc_window_overflow_isr 158 159 .global _sparc_window_underflow_isr 160 .type _sparc_window_underflow_isr, #function 161_sparc_window_underflow_isr: 162 rd %wim, %l3 163 /* l4 := WIM << 1 */ 164 sll %l3, 1, %l4 165 /* l5 := WIM >> (NWIN-1) */ 166 srl %l3, (SPARC_NWIN-1), %l5 167 /* WIM := (WIM << 1) ^ (WIM >> (NWIN-1)) */ 168 wr %l4, %l5, %wim 169 /* WIM is implicitly read so nops are needed. */ 170 nop 171 nop 172 nop 173 174 /* Enter the window to restore requires two restore instructions. */ 175 restore 176 restore 177 ldd [%sp + 0x00], %l0 178 ldd [%sp + 0x08], %l2 179 ldd [%sp + 0x10], %l4 180 ldd [%sp + 0x18], %l6 181 ldd [%sp + 0x20], %i0 182 ldd [%sp + 0x28], %i2 183 ldd [%sp + 0x30], %i4 184 ldd [%sp + 0x38], %i6 185 /* Go back to the trap window. */ 186 save 187 save 188 /* Re-execute restore. */ 189 jmp %l1 190 rett %l2 191 .size _sparc_window_underflow_isr, .-_sparc_window_underflow_isr 192 193 .global _sparc_window_flush_isr 194 .type _sparc_window_flush_isr, #function 195_sparc_window_flush_isr: 196 /* 197 * push a few registers which are needed later to the stack using 198 * sp from the window we trapped from (which is fp in this window) 199 */ 200 sub %fp, 0x10, %fp 201 std %l0, [%fp + 0x40 + 0x00] 202 st %l2, [%fp + 0x40 + 0x08] 203 st %g1, [%fp + 0x40 + 0x0c] 204 205 restore 206 /* In window where we trapped from. This window will not be flushed. */ 207 208 /* Set highest processor interrupt level and enable traps. */ 209 rd %psr, %g1 210 or %g1, PSR_PIL, %g1 211 wr %g1, PSR_ET, %psr 212 nop 213 nop 214 215 /* Execute "save" NWINDOWS-1 times. */ 216 set SPARC_NWIN-2, %g1 2171: 218 save 219 cmp %g1, %g0 220 bne 1b 221 sub %g1, 1, %g1 222 223 /* Execute "restore" NWINDOWS-1 times. */ 224 set SPARC_NWIN-2, %g1 2252: 226 restore 227 cmp %g1, %g0 228 bne 2b 229 sub %g1, 1, %g1 230 231 save 232 233 /* pop registers from stack which are used for the trap return */ 234 ldd [%fp + 0x40 + 0x00], %l0 235 ld [%fp + 0x40 + 0x08], %l2 236 ld [%fp + 0x40 + 0x0c], %g1 237 add %fp, 0x10, %fp 238 239 /* Restore %psr as it was on trap entry. */ 240 wr %l0, %psr 241 nop 242 nop 243 nop 244 245 jmp %l2 246 rett %l2 + 4 247 .size _sparc_window_flush_isr, .-_sparc_window_flush_isr 248