1/* 2Copyright (c) 2013 Andes Technology Corporation. 3All rights reserved. 4 5Redistribution and use in source and binary forms, with or without 6modification, are permitted provided that the following conditions are met: 7 8 Redistributions of source code must retain the above copyright 9 notice, this list of conditions and the following disclaimer. 10 11 Redistributions in binary form must reproduce the above copyright 12 notice, this list of conditions and the following disclaimer in the 13 documentation and/or other materials provided with the distribution. 14 15 The name of the company may not be used to endorse or promote 16 products derived from this software without specific prior written 17 permission. 18 19THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22DISCLAIMED. IN NO EVENT SHALL RED HAT INCORPORATED BE LIABLE FOR ANY 23DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 28SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 30 31The setjmp/longjmp for nds32. 32The usage of thirty-two 32-bit General Purpose Registers (GPR): 33 $r28 : $fp 34 $r29 : $gp 35 $r30 : $lp 36 $r31 : $sp 37 38 caller-save registers: $r0 ~ $r5, $r16 ~ $r23 39 callee-save registers: $r6 ~ $r10, $r11 ~ $r14 40 reserved for assembler : $r15 41 reserved for other use : $r24, $r25, $r26, $r27 42 43Save all callee-save registers and $fp, $gp, $lp and $sp is enough in theory. 44For debugging issue, the layout of jum_buf in here should be in sync with GDB. 45The $r16 ~ $r19 are used to store D0/D1, keep them for backward-compatible. 46*/ 47 48/* int setjmp(jmp_buf env); */ 49#include <picolibc.h> 50 51 .text 52 .align 2 53 .global setjmp 54 .type setjmp, @function 55setjmp: 56#if __NDS32_REDUCED_REGS__ 57 smw.bim $r6, [$r0], $r10, #0b0000 58 addi $r0, $r0, #32 /* Leave room to keep jum_buf all the same. */ 59 smw.bim $r31, [$r0], $r31, #0b1111 60#else 61 smw.bim $r6, [$r0], $r14, #0b0000 62 smw.bim $r16, [$r0], $r19, #0b1111 63#endif 64 65#if __NDS32_EXT_FPU_SP__ || __NDS32_EXT_FPU_DP__ 66 67 /* Extract $fpcfg.freg (b[3:2]), then save into jmp_buf. */ 68 fmfcfg $r2 69 slli $r2, $r2, #28 70 srli $r2, $r2, #30 71 swi.bi $r2, [$r0], #4 72 73 /* Make sure $r0 is double-word-aligned. */ 74 addi $r0, $r0, #7 75 bitci $r0, $r0, #7 76 77 /* Case switch according to $fpcfg.freg */ 78 beqz $r2, .LCFG0_save /* Branch if $fpcfg.freg = 0b00. */ 79 xori $r15, $r2, #0b10 80 beqz $r15, .LCFG2_save /* Branch $fpcfg.freg = 0b10. */ 81 srli $r2, $r2, #0b01 82 beqz $r2, .LCFG1_save /* Branch if $fpcfg.freg = 0b01. */ 83 /* Fall-through if $fpcfg.freg = 0b11. */ 84.LCFG3_save: 85 fsdi.bi $fd31, [$r0], #8 86 fsdi.bi $fd29, [$r0], #8 87 fsdi.bi $fd27, [$r0], #8 88 fsdi.bi $fd25, [$r0], #8 89 fsdi.bi $fd23, [$r0], #8 90 fsdi.bi $fd21, [$r0], #8 91 fsdi.bi $fd19, [$r0], #8 92 fsdi.bi $fd17, [$r0], #8 93.LCFG2_save: 94 fsdi.bi $fd15, [$r0], #8 95 fsdi.bi $fd13, [$r0], #8 96 fsdi.bi $fd11, [$r0], #8 97 fsdi.bi $fd9, [$r0], #8 98.LCFG1_save: 99 fsdi.bi $fd7, [$r0], #8 100 fsdi.bi $fd5, [$r0], #8 101.LCFG0_save: 102 fsdi.bi $fd3, [$r0], #8 103#endif 104 105 /* Set return value to zero. */ 106 movi $r0, 0 107 ret 108 .size setjmp, .-setjmp 109 110 111/* void longjmp(jmp_buf env, int val); */ 112 .text 113 .align 2 114 .global longjmp 115 .type longjmp, @function 116longjmp: 117#if __NDS32_REDUCED_REGS__ 118 lmw.bim $r6, [$r0], $r10, #0b0000 119 addi $r0, $r0, #32 120 lmw.bim $r31, [$r0], $r31, #0b1111 121#else 122 lmw.bim $r6, [$r0], $r14, #0b0000 123 lmw.bim $r16, [$r0], $r19, #0b1111 124#endif 125 126#if __NDS32_EXT_FPU_SP__ || __NDS32_EXT_FPU_DP__ 127 128 /* Restore value of $fpcfg.freg (b[3:2]). */ 129 lwi.bi $r2, [$r0], #4 130 131 /* Make sure $r0 is double-word-aligned. */ 132 addi $r0, $r0, #7 133 bitci $r0, $r0, #7 134 135 /* Case switch according to $fpcfg.freg */ 136 beqz $r2, .LCFG0_restore /* Branch if $fpcfg.freg = 0b00. */ 137 xori $r15, $r2, #0b10 138 beqz $r15, .LCFG2_restore /* Branch $fpcfg.freg = 0b10. */ 139 srli $r2, $r2, #0b01 140 beqz $r2, .LCFG1_restore /* Branch if $fpcfg.freg = 0b01. */ 141 /* Fall-through if $fpcfg.freg = 0b11. */ 142.LCFG3_restore: 143 fldi.bi $fd31, [$r0], #8 144 fldi.bi $fd29, [$r0], #8 145 fldi.bi $fd27, [$r0], #8 146 fldi.bi $fd25, [$r0], #8 147 fldi.bi $fd23, [$r0], #8 148 fldi.bi $fd21, [$r0], #8 149 fldi.bi $fd19, [$r0], #8 150 fldi.bi $fd17, [$r0], #8 151.LCFG2_restore: 152 fldi.bi $fd15, [$r0], #8 153 fldi.bi $fd13, [$r0], #8 154 fldi.bi $fd11, [$r0], #8 155 fldi.bi $fd9, [$r0], #8 156.LCFG1_restore: 157 fldi.bi $fd7, [$r0], #8 158 fldi.bi $fd5, [$r0], #8 159.LCFG0_restore: 160 fldi.bi $fd3, [$r0], #8 161#endif 162 163 /* Set val as return value. If the value val is 0, 1 will be returned 164 instead. */ 165 movi $r0, 1 166 cmovn $r0, $r1, $r1 /* r0=(r1!=0)? r1: r0 */ 167 ret 168 .size longjmp, .-longjmp 169