1/* 2 * Copyright (c) 2019-2020 Cobham Gaisler AB 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7#include <zephyr/toolchain.h> 8#include <zephyr/linker/sections.h> 9#include <offsets_short.h> 10#include <zephyr/arch/sparc/sparc.h> 11 12GTEXT(__sparc_trap_except_reason) 13GTEXT(__sparc_trap_fault) 14 15/* 16 * Fault trap handler 17 * 18 * - IU state is saved and restored 19 * 20 * On entry: 21 * %l0: psr (set by trap code) 22 * %l1: pc 23 * %l2: npc 24 * %l6: tbr (set by trap code) 25 * %fp: %sp of current register window at trap time 26 * %g1: reason 27 * 28 * This trap handler will trash some of the global registers, which is OK since 29 * we will not return to where we trapped. 30 */ 31SECTION_FUNC(TEXT, __sparc_trap_except_reason) 32 mov %g1, %l7 33.Ldoit: 34 /* %g2, %g3 are used at manual window overflow so save temporarily */ 35 mov %g2, %l4 36 mov %g3, %l5 37 38 /* We may have trapped into the invalid window. If so, make it valid. */ 39 rd %wim, %g2 40 mov %g2, %l3 41 srl %g2, %l0, %g3 42 cmp %g3, 1 43 bne .Lwodone 44 nop 45 46 /* Do the window overflow. */ 47 sll %g2, (CONFIG_SPARC_NWIN-1), %g3 48 srl %g2, 1, %g2 49 or %g2, %g3, %g2 50 51 /* Enter window to save. */ 52 save 53 /* Install new wim calculated above. */ 54 mov %g2, %wim 55 nop 56 nop 57 nop 58 /* Put registers on the dedicated save area of the ABI stack frame. */ 59 std %l0, [%sp + 0x00] 60 std %l2, [%sp + 0x08] 61 std %l4, [%sp + 0x10] 62 std %l6, [%sp + 0x18] 63 std %i0, [%sp + 0x20] 64 std %i2, [%sp + 0x28] 65 std %i4, [%sp + 0x30] 66 std %i6, [%sp + 0x38] 67 /* Leave saved window. */ 68 restore 69 70.Lwodone: 71 mov %l4, %g2 72 mov %l5, %g3 73 74 /* Allocate an ABI stack frame and exception stack frame */ 75 sub %fp, 96 + __struct_arch_esf_SIZEOF, %sp 76 /* 77 * %fp: %sp of interrupted task 78 * %sp: %sp of interrupted task - ABI_frame - esf 79 */ 80 81 mov %l7, %o0 82 /* Fill in the content of the exception stack frame */ 83#if defined(CONFIG_EXTRA_EXCEPTION_INFO) 84 std %i0, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x00] 85 std %i2, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x08] 86 std %i4, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x10] 87 std %i6, [%sp + 96 + __struct_arch_esf_out_OFFSET + 0x18] 88 std %g0, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x00] 89 std %g2, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x08] 90 std %g4, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x10] 91 std %g6, [%sp + 96 + __struct_arch_esf_global_OFFSET + 0x18] 92#endif 93 std %l0, [%sp + 96 + __struct_arch_esf_psr_OFFSET] /* psr pc */ 94 std %l2, [%sp + 96 + __struct_arch_esf_npc_OFFSET] /* npc wim */ 95 rd %y, %l7 96 std %l6, [%sp + 96 + __struct_arch_esf_tbr_OFFSET] /* tbr y */ 97 98 /* Enable traps, raise PIL to mask all maskable interrupts. */ 99 or %l0, PSR_PIL, %o2 100 wr %o2, PSR_ET, %psr 101 nop 102 nop 103 nop 104 105#if defined(CONFIG_EXTRA_EXCEPTION_INFO) 106 /* Flush all register windows to the stack. */ 107 .rept CONFIG_SPARC_NWIN-1 108 save %sp, -64, %sp 109 .endr 110 .rept CONFIG_SPARC_NWIN-1 111 restore 112 .endr 113#endif 114 115 /* 116 * reason is the first argument. 117 * Exception stack frame prepared earlier is the second argument. 118 */ 119 call z_sparc_fatal_error 120 add %sp, 96, %o1 121 122 123/* 124 * Entry for trap we don't handle explicitly 125 * 126 * Just drop into __sparc_trap_except_reason with reason set to 127 * K_ERR_CPU_EXCEPTION. Note that "reason" is transported in %l7 of the 128 * trapped-into window and global %g1 is preserved. 129 */ 130SECTION_FUNC(TEXT, __sparc_trap_fault) 131 b .Ldoit 132 /* K_ERR_CPU_EXCEPTION */ 133 mov %g0, %l7 134