1/* 2 * Copyright (c) 2019-2020 Cobham Gaisler AB 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7/* 8 * This file contains standard handlers for the SPARC V8 window overflow and 9 * underflow traps. It also implements the handler for SPARC-ABI 10 * "Flush windows" which is used for example by longjmp() and C++ exceptions. 11 */ 12 13#include <zephyr/toolchain.h> 14#include <zephyr/linker/sections.h> 15#include <zephyr/arch/sparc/sparc.h> 16 17GTEXT(__sparc_trap_window_overflow) 18GTEXT(__sparc_trap_window_underflow) 19GTEXT(__sparc_trap_flush_windows) 20 21SECTION_FUNC(TEXT, __sparc_trap_window_overflow) 22 /* Enter the window to be stored. */ 23 save 24 /* Save local register set. */ 25 std %l0, [%sp + 0x00] 26 std %l2, [%sp + 0x08] 27 std %l4, [%sp + 0x10] 28 rd %wim, %l3 29 std %l6, [%sp + 0x18] 30 /* l2 := WIM << (NWIN-1) */ 31 sll %l3, (CONFIG_SPARC_NWIN-1), %l2 32 /* Save input register set. */ 33 std %i0, [%sp + 0x20] 34 /* l3 := WIM >> 1 */ 35 srl %l3, 1, %l3 36 std %i2, [%sp + 0x28] 37 /* WIM := (WIM >> 1) ^ (WIM << (NWIN-1)) */ 38 wr %l3, %l2, %wim 39 /* NOTE: 3 instruction before restore (delayed write instruction) */ 40 std %i4, [%sp + 0x30] 41 nop 42 std %i6, [%sp + 0x38] 43 /* Go back to trap window. */ 44 restore 45 /* Re-execute save. */ 46 jmp %l1 47 rett %l2 48 49SECTION_FUNC(TEXT, __sparc_trap_window_underflow) 50 rd %wim, %l3 51 /* l4 := WIM << 1 */ 52 sll %l3, 1, %l4 53 /* l5 := WIM >> (NWIN-1) */ 54 srl %l3, (CONFIG_SPARC_NWIN-1), %l5 55 /* WIM := (WIM << 1) ^ (WIM >> (NWIN-1)) */ 56 wr %l4, %l5, %wim 57 /* WIM is implicitly read so nops are needed. */ 58 nop 59 nop 60 nop 61 62 /* Enter the window to restore requires two restore instructions. */ 63 restore 64 restore 65 ldd [%sp + 0x00], %l0 66 ldd [%sp + 0x08], %l2 67 ldd [%sp + 0x10], %l4 68 ldd [%sp + 0x18], %l6 69 ldd [%sp + 0x20], %i0 70 ldd [%sp + 0x28], %i2 71 ldd [%sp + 0x30], %i4 72 ldd [%sp + 0x38], %i6 73 /* Go back to the trap window. */ 74 save 75 save 76 /* Re-execute restore. */ 77 jmp %l1 78 rett %l2 79 80/* 81 * Handler for SPARC trap 0x83: trap_instruction, defined as "Flush windows" by 82 * SPARC-ABI: 83 * "By executing a type 3 trap, a process asks the system to flush all its 84 * register windows to the stack." 85 * 86 * On entry: 87 * %l0: psr 88 * %l1: pc 89 * %l2: npc 90 */ 91SECTION_FUNC(TEXT, __sparc_trap_flush_windows) 92 /* Save global registers used by the routine */ 93 mov %g3, %l3 94 mov %g4, %l4 95 mov %g5, %l5 96 mov %g1, %l6 97 mov %g2, %l7 98 99 /* Uses g3=psr, g4=1, g2=wim, g1,g5=scratch */ 100 mov %l0, %g3 101 set 1, %g4 102 rd %wim, %g2 103 104 /* 105 * We can always restore the previous window. Check if we can restore 106 * the window after that. 107 */ 108 and %l0, PSR_CWP, %g1 109 add %g1, 2, %g1 110 ba .LcheckNextWindow 111 restore 112 113 /* Flush window to stack */ 114.LflushWindow: 115 std %l0, [%sp + 0x00] 116 std %l2, [%sp + 0x08] 117 std %l4, [%sp + 0x10] 118 std %l6, [%sp + 0x18] 119 std %i0, [%sp + 0x20] 120 std %i2, [%sp + 0x28] 121 std %i4, [%sp + 0x30] 122 std %i6, [%sp + 0x38] 123 124 /* 125 * Check if next window is invalid by comparing 126 * (1 << ((cwp + 1) % NWIN)) with WIM 127 */ 128.LcheckNextWindow: 129 set CONFIG_SPARC_NWIN, %g5 130 cmp %g1, %g5 131 bge,a .Lnowrap 132 sub %g1, %g5, %g1 133.Lnowrap: 134 sll %g4, %g1, %g5 135 cmp %g5, %g2 136 be .LflushWindowDone 137 inc %g1 138 139 /* We need to flush the next window */ 140 ba .LflushWindow 141 restore 142 143 /* 144 * All used windows have been flushed. Set WIM to cause trap for CWP+2. 145 * When we return from this trap it will be CWP+1 that will trap, that 146 * is, the next restore or rett. 147 */ 148.LflushWindowDone: 149 /* We can not restore %psr from %l0 because we may be in any window. */ 150 wr %g3, %psr 151 and %g3, PSR_CWP, %g1 152 add %g1, 2, %g1 153 set CONFIG_SPARC_NWIN, %g5 154 /* We are now back in the trap window. */ 155 cmp %g1, %g5 156 bge,a .Lnowrap2 157 sub %g1, %g5, %g1 158.Lnowrap2: 159 sll %g4, %g1, %g1 160 wr %g1, %wim 161 mov %l3, %g3 162 mov %l4, %g4 163 mov %l5, %g5 164 mov %l6, %g1 165 mov %l7, %g2 166 jmp %l2 167 rett %l2 + 4 168