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 .text 50 .align 2 51 .global setjmp 52 .type setjmp, @function 53setjmp: 54#if __NDS32_REDUCED_REGS__ 55 smw.bim $r6, [$r0], $r10, #0b0000 56 addi $r0, $r0, #32 /* Leave room to keep jum_buf all the same. */ 57 smw.bim $r31, [$r0], $r31, #0b1111 58#else 59 smw.bim $r6, [$r0], $r14, #0b0000 60 smw.bim $r16, [$r0], $r19, #0b1111 61#endif 62 63#if __NDS32_EXT_FPU_SP__ || __NDS32_EXT_FPU_DP__ 64 65 /* Extract $fpcfg.freg (b[3:2]), then save into jmp_buf. */ 66 fmfcfg $r2 67 slli $r2, $r2, #28 68 srli $r2, $r2, #30 69 swi.bi $r2, [$r0], #4 70 71 /* Make sure $r0 is double-word-aligned. */ 72 addi $r0, $r0, #7 73 bitci $r0, $r0, #7 74 75 /* Case switch according to $fpcfg.freg */ 76 beqz $r2, .LCFG0_save /* Branch if $fpcfg.freg = 0b00. */ 77 xori $r15, $r2, #0b10 78 beqz $r15, .LCFG2_save /* Branch $fpcfg.freg = 0b10. */ 79 srli $r2, $r2, #0b01 80 beqz $r2, .LCFG1_save /* Branch if $fpcfg.freg = 0b01. */ 81 /* Fall-through if $fpcfg.freg = 0b11. */ 82.LCFG3_save: 83 fsdi.bi $fd31, [$r0], #8 84 fsdi.bi $fd29, [$r0], #8 85 fsdi.bi $fd27, [$r0], #8 86 fsdi.bi $fd25, [$r0], #8 87 fsdi.bi $fd23, [$r0], #8 88 fsdi.bi $fd21, [$r0], #8 89 fsdi.bi $fd19, [$r0], #8 90 fsdi.bi $fd17, [$r0], #8 91.LCFG2_save: 92 fsdi.bi $fd15, [$r0], #8 93 fsdi.bi $fd13, [$r0], #8 94 fsdi.bi $fd11, [$r0], #8 95 fsdi.bi $fd9, [$r0], #8 96.LCFG1_save: 97 fsdi.bi $fd7, [$r0], #8 98 fsdi.bi $fd5, [$r0], #8 99.LCFG0_save: 100 fsdi.bi $fd3, [$r0], #8 101#endif 102 103 /* Set return value to zero. */ 104 movi $r0, 0 105 ret 106 .size setjmp, .-setjmp 107 108 109/* void longjmp(jmp_buf env, int val); */ 110 .text 111 .align 2 112 .global longjmp 113 .type longjmp, @function 114longjmp: 115#if __NDS32_REDUCED_REGS__ 116 lmw.bim $r6, [$r0], $r10, #0b0000 117 addi $r0, $r0, #32 118 lmw.bim $r31, [$r0], $r31, #0b1111 119#else 120 lmw.bim $r6, [$r0], $r14, #0b0000 121 lmw.bim $r16, [$r0], $r19, #0b1111 122#endif 123 124#if __NDS32_EXT_FPU_SP__ || __NDS32_EXT_FPU_DP__ 125 126 /* Restore value of $fpcfg.freg (b[3:2]). */ 127 lwi.bi $r2, [$r0], #4 128 129 /* Make sure $r0 is double-word-aligned. */ 130 addi $r0, $r0, #7 131 bitci $r0, $r0, #7 132 133 /* Case switch according to $fpcfg.freg */ 134 beqz $r2, .LCFG0_restore /* Branch if $fpcfg.freg = 0b00. */ 135 xori $r15, $r2, #0b10 136 beqz $r15, .LCFG2_restore /* Branch $fpcfg.freg = 0b10. */ 137 srli $r2, $r2, #0b01 138 beqz $r2, .LCFG1_restore /* Branch if $fpcfg.freg = 0b01. */ 139 /* Fall-through if $fpcfg.freg = 0b11. */ 140.LCFG3_restore: 141 fldi.bi $fd31, [$r0], #8 142 fldi.bi $fd29, [$r0], #8 143 fldi.bi $fd27, [$r0], #8 144 fldi.bi $fd25, [$r0], #8 145 fldi.bi $fd23, [$r0], #8 146 fldi.bi $fd21, [$r0], #8 147 fldi.bi $fd19, [$r0], #8 148 fldi.bi $fd17, [$r0], #8 149.LCFG2_restore: 150 fldi.bi $fd15, [$r0], #8 151 fldi.bi $fd13, [$r0], #8 152 fldi.bi $fd11, [$r0], #8 153 fldi.bi $fd9, [$r0], #8 154.LCFG1_restore: 155 fldi.bi $fd7, [$r0], #8 156 fldi.bi $fd5, [$r0], #8 157.LCFG0_restore: 158 fldi.bi $fd3, [$r0], #8 159#endif 160 161 /* Set val as return value. If the value val is 0, 1 will be returned 162 instead. */ 163 movi $r0, 1 164 cmovn $r0, $r1, $r1 /* r0=(r1!=0)? r1: r0 */ 165 ret 166 .size longjmp, .-longjmp 167