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#define SPARC_NWIN 8 37 38#define PSR_VER_BIT 24 39#define PSR_PIL_BIT 8 40 41#define PSR_VER (0xf << PSR_VER_BIT) 42#define PSR_EF (1 << 12) 43#define PSR_S (1 << 7) 44#define PSR_PS (1 << 6) 45#define PSR_ET (1 << 5) 46#define PSR_PIL (0xf << PSR_PIL_BIT) 47#define PSR_CWP 0x1f 48 49#define TRAP(func) \ 50 rd %psr, %l0 ; \ 51 sethi %hi(_sparc_ ## func ## _isr), %l4 ;\ 52 jmp %l4+%lo(_sparc_ ## func ## _isr) ;\ 53 rd %tbr, %l6 ; 54 55#define TRAP_IN_TRAP \ 56 ta 0x00 ; \ 57 nop ; \ 58 nop ; \ 59 nop ; 60 61#define TRAP_HALT(name) \ 62 TRAP(name) ; \ 63 .weak _sparc_ ## name ## _isr ; \ 64 .equ _sparc_ ## name ## _isr, _sparc_halt_isr ; 65 66 .section .data.init.enter 67 .globl __weak_interrupt_vector 68__weak_interrupt_vector: 69 TRAP(reset) 70 TRAP_HALT(instruction_access_exception) 71 TRAP_HALT(illegal_instruction) 72 TRAP_HALT(priveledged_instruction) 73 TRAP_HALT(fp_disabled) 74#ifdef _FLAT 75 TRAP_HALT(window_overflow) 76 TRAP_HALT(window_underflow) 77#else 78 TRAP(window_overflow) 79 TRAP(window_underflow) 80#endif 81 TRAP_HALT(mem_address_not_aligned) 82 TRAP_HALT(fp_exception) 83 TRAP_HALT(data_access_exception) 84 TRAP_HALT(tag_overflow) 85 TRAP_HALT(watchpoint_detected) 86 TRAP_HALT(trap_0c) 87 TRAP_HALT(trap_0d) 88 TRAP_HALT(trap_0e) 89 TRAP_HALT(trap_0f) 90 TRAP_HALT(trap_10) 91 92 . = __weak_interrupt_vector + 0x80 * 16 93 94 TRAP_HALT(syscall) 95 TRAP_HALT(breakpoint) 96 TRAP_HALT(divide_by_zero) 97#ifdef _FLAT 98 TRAP_HALT(window_flush) 99#else 100 TRAP(window_flush) 101#endif 102 TRAP_HALT(clean_windows) 103 .size __weak_interrupt_vector, . - __weak_interrupt_vector 104 .weak __interrupt_vector 105 .equ __interrupt_vector, __weak_interrupt_vector 106 107 .text 108 .align 4 109 110 .global _sparc_reset_isr 111 .type _sparc_reset_isr, #function 112_sparc_reset_isr: 113 sethi %hi(_start), %g4 114 jmp %g4+%lo(_start) 115 nop 116 .size _sparc_reset_isr, .-_sparc_reset_isr 117 118 .global _sparc_halt_isr 119 .type _sparc_halt_isr, #function 120_sparc_halt_isr: 121 ta 0x00 122 ba _sparc_halt_isr 123 nop 124 .size _sparc_halt_isr, .-_sparc_halt_isr 125 126 .global _sparc_window_overflow_isr 127 .type _sparc_window_overflow_isr, #function 128_sparc_window_overflow_isr: 129 /* Enter the window to be stored. */ 130 save 131 /* Save local register set. */ 132 std %l0, [%sp + 0x00] 133 std %l2, [%sp + 0x08] 134 std %l4, [%sp + 0x10] 135 rd %wim, %l3 136 std %l6, [%sp + 0x18] 137 /* l2 := WIM << (NWIN-1) */ 138 sll %l3, (SPARC_NWIN-1), %l2 139 /* Save input register set. */ 140 std %i0, [%sp + 0x20] 141 /* l3 := WIM >> 1 */ 142 srl %l3, 1, %l3 143 std %i2, [%sp + 0x28] 144 /* WIM := (WIM >> 1) ^ (WIM << (NWIN-1)) */ 145 wr %l3, %l2, %wim 146 /* NOTE: 3 instruction before restore (delayed write instruction) */ 147 std %i4, [%sp + 0x30] 148 nop 149 std %i6, [%sp + 0x38] 150 /* Go back to trap window. */ 151 restore 152 /* Re-execute save. */ 153 jmp %l1 154 rett %l2 155 .size _sparc_window_overflow_isr, .-_sparc_window_overflow_isr 156 157 .global _sparc_window_underflow_isr 158 .type _sparc_window_underflow_isr, #function 159_sparc_window_underflow_isr: 160 rd %wim, %l3 161 /* l4 := WIM << 1 */ 162 sll %l3, 1, %l4 163 /* l5 := WIM >> (NWIN-1) */ 164 srl %l3, (SPARC_NWIN-1), %l5 165 /* WIM := (WIM << 1) ^ (WIM >> (NWIN-1)) */ 166 wr %l4, %l5, %wim 167 /* WIM is implicitly read so nops are needed. */ 168 nop 169 nop 170 nop 171 172 /* Enter the window to restore requires two restore instructions. */ 173 restore 174 restore 175 ldd [%sp + 0x00], %l0 176 ldd [%sp + 0x08], %l2 177 ldd [%sp + 0x10], %l4 178 ldd [%sp + 0x18], %l6 179 ldd [%sp + 0x20], %i0 180 ldd [%sp + 0x28], %i2 181 ldd [%sp + 0x30], %i4 182 ldd [%sp + 0x38], %i6 183 /* Go back to the trap window. */ 184 save 185 save 186 /* Re-execute restore. */ 187 jmp %l1 188 rett %l2 189 .size _sparc_window_underflow_isr, .-_sparc_window_underflow_isr 190 191 .global _sparc_window_flush_isr 192 .type _sparc_window_flush_isr, #function 193_sparc_window_flush_isr: 194 /* 195 * push a few registers which are needed later to the stack using 196 * sp from the window we trapped from (which is fp in this window) 197 */ 198 sub %fp, 0x10, %fp 199 std %l0, [%fp + 0x40 + 0x00] 200 st %l2, [%fp + 0x40 + 0x08] 201 st %g1, [%fp + 0x40 + 0x0c] 202 203 restore 204 /* In window where we trapped from. This window will not be flushed. */ 205 206 /* Set highest processor interrupt level and enable traps. */ 207 rd %psr, %g1 208 or %g1, PSR_PIL, %g1 209 wr %g1, PSR_ET, %psr 210 nop 211 nop 212 213 /* Execute "save" NWINDOWS-1 times. */ 214 set SPARC_NWIN-2, %g1 2151: 216 save 217 cmp %g1, %g0 218 bne 1b 219 sub %g1, 1, %g1 220 221 /* Execute "restore" NWINDOWS-1 times. */ 222 set SPARC_NWIN-2, %g1 2232: 224 restore 225 cmp %g1, %g0 226 bne 2b 227 sub %g1, 1, %g1 228 229 save 230 231 /* pop registers from stack which are used for the trap return */ 232 ldd [%fp + 0x40 + 0x00], %l0 233 ld [%fp + 0x40 + 0x08], %l2 234 ld [%fp + 0x40 + 0x0c], %g1 235 add %fp, 0x10, %fp 236 237 /* Restore %psr as it was on trap entry. */ 238 wr %l0, %psr 239 nop 240 nop 241 nop 242 243 jmp %l2 244 rett %l2 + 4 245 .size _sparc_window_flush_isr, .-_sparc_window_flush_isr 246