| /* A setjmp.c for CRIS |
| Copyright (C) 1993-2005 Axis Communications. |
| All rights reserved. |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions |
| are met: |
| |
| 1. Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| |
| 2. Neither the name of Axis Communications nor the names of its |
| contributors may be used to endorse or promote products derived |
| from this software without specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED BY AXIS COMMUNICATIONS AND ITS CONTRIBUTORS |
| ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL AXIS |
| COMMUNICATIONS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
| INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
| IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| POSSIBILITY OF SUCH DAMAGE. */ |
| |
| /* For benefit of CRIS v0..v3, we save and restore CCR to be able to |
| correctly handle DI/EI; otherwise there would be no reason to save it. |
| Note also that the "move x,ccr" does NOT affect |
| the DMA enable bits (E and D) of v0..v3. |
| |
| We do not save mof; it is call-clobbered. It also does not exist in |
| v0..v8; it should be safe to read or write to it there, but better not. |
| |
| jmp_buf[0] - PC |
| jmp_buf[1] - SP (R14) |
| jmp_buf[2] - R13 |
| jmp_buf[3] - R12 |
| jmp_buf[4] - R11 |
| jmp_buf[5] - R10 |
| jmp_buf[6] - R9 |
| jmp_buf[7] - R8 |
| jmp_buf[8] - R7 |
| jmp_buf[9] - R6 |
| jmp_buf[10] - R5 |
| jmp_buf[11] - R4 |
| jmp_buf[12] - R3 |
| jmp_buf[13] - R2 |
| jmp_buf[14] - R1 |
| jmp_buf[15] - R0 |
| jmp_buf[16] - SRP |
| jmp_buf[17] - CCR |
| */ |
| |
| #include <setjmp.h> |
| |
| int |
| setjmp (jmp_buf buf) |
| { |
| int ret; |
| #if defined (__arch_common_v10_v32) || defined (__arch_v32) |
| /* No offsets in the compatibility mode. Also, movem saves in |
| different order on v10 than on v32, so we use single move |
| instructions instead, this not being a speed-prioritized operation. |
| And we don't save CCR or CCS; since long unuseful. */ |
| __asm__ __volatile__ |
| ("move.d %1,$r13 \n\ |
| move 0f,$mof \n\ |
| move $mof,[$r13+] \n\ |
| move.d $sp,[$r13+] \n\ |
| clear.d [$r13+] \n\ |
| move.d $r12,[$r13+] \n\ |
| move.d $r11,[$r13+] \n\ |
| move.d $r10,[$r13+] \n\ |
| moveq 1,$r9 \n\ |
| move.d $r9,[$r13+] \n\ |
| move.d $r8,[$r13+] \n\ |
| move.d $r7,[$r13+] \n\ |
| move.d $r6,[$r13+] \n\ |
| move.d $r5,[$r13+] \n\ |
| move.d $r4,[$r13+] \n\ |
| move.d $r3,[$r13+] \n\ |
| move.d $r2,[$r13+] \n\ |
| move.d $r1,[$r13+] \n\ |
| move.d $r0,[$r13+] \n\ |
| move $srp,[$r13+] \n\ |
| clear.d [$r13+] \n\ |
| clear.d $r9 \n\ |
| 0: \n\ |
| move.d $r9,%0" |
| |
| /* Output. */ |
| : "=&r" (ret) |
| |
| /* Input. */ |
| : "r" (buf) |
| |
| /* Clobber. */ |
| : "r9", "r13", "memory"); |
| #else /* not __arch_common_v10_v32 or __arch_v32 */ |
| #ifdef __PIC__ |
| __asm__ __volatile__ |
| ("moveq 1,$r9 \n\ |
| movem $sp,[%1+1*4] \n\ |
| move.d $pc,$r9 \n\ |
| addq 0f-.,$r9 \n\ |
| move.d $r9,[%1] \n\ |
| move $srp,[%1+16*4] \n\ |
| move $ccr,[%1+17*4] \n\ |
| clear.d $r9 \n\ |
| 0: \n\ |
| move.d $r9,%0" |
| |
| /* Output. */ |
| : "=&r" (ret) |
| |
| /* Input. */ |
| : "r" (buf) |
| |
| /* Clobber. */ |
| : "r9", "memory"); |
| #else /* not PIC */ |
| __asm__ __volatile__ |
| ("moveq 1,$r9 \n\ |
| movem $sp,[%1+1*4] \n\ |
| move.d 0f,$r9 \n\ |
| move.d $r9,[%1] \n\ |
| move $srp,[%1+16*4] \n\ |
| move $ccr,[%1+17*4] \n\ |
| clear.d $r9 \n\ |
| 0: \n\ |
| move.d $r9,%0" |
| |
| /* Output. */ |
| : "=&r" (ret) |
| |
| /* Input. */ |
| : "r" (buf) |
| |
| /* Clobber. */ |
| : "r9"); |
| #endif /* not PIC */ |
| #endif /* not __arch_common_v10_v32 or __arch_v32 */ |
| return ret; |
| } |
| |
| void |
| longjmp(jmp_buf buf, int val) |
| { |
| #if defined (__arch_common_v10_v32) || defined (__arch_v32) |
| __asm__ __volatile__ |
| ("cmpq 0,%1 \n\ |
| beq 0f \n\ |
| move.d %0,$r13 ; In delay-slot. \n\ |
| addq 6*4,$r13 \n\ |
| move.d %1,[$r13] \n\ |
| subq 6*4,$r13 \n\ |
| 0:\n" |
| #ifdef __arch_common_v10_v32 |
| /* Cater to branch offset difference between v32 and v10. We |
| assume the branch above is 8-bit. */ |
| " setf\n" |
| #endif |
| " move [$r13+],$mof \n\ |
| move.d [$r13+],$sp \n\ |
| addq 4,$r13 \n\ |
| move.d [$r13+],$r12 \n\ |
| move.d [$r13+],$r11 \n\ |
| move.d [$r13+],$r10 \n\ |
| move.d [$r13+],$r9 \n\ |
| move.d [$r13+],$r8 \n\ |
| move.d [$r13+],$r7 \n\ |
| move.d [$r13+],$r6 \n\ |
| move.d [$r13+],$r5 \n\ |
| move.d [$r13+],$r4 \n\ |
| move.d [$r13+],$r3 \n\ |
| move.d [$r13+],$r2 \n\ |
| move.d [$r13+],$r1 \n\ |
| move.d [$r13+],$r0 \n\ |
| move [$r13+],$srp \n\ |
| move $mof,$r13 \n\ |
| jump $r13 \n\ |
| setf" |
| |
| /* No outputs. */ |
| : |
| |
| /* Inputs. */ |
| : "r" (buf), "r" (val) |
| : "r13", "memory"); |
| |
| #else /* not __arch_common_v10_v32 or __arch_v32 */ |
| __asm__ __volatile__ |
| ("move [%0+17*4],$ccr \n\ |
| move [%0+16*4],$srp \n\ |
| test.d %1 \n\ |
| beq 0f \n\ |
| nop \n\ |
| move.d %1,[%0+6*4] ; Offset for r9. \n\ |
| 0: \n\ |
| movem [%0],$pc" |
| |
| /* No outputs. */ |
| : |
| |
| /* Inputs. */ |
| : "r" (buf), "r" (val) |
| : "memory"); |
| #endif /* not __arch_common_v10_v32 or __arch_v32 */ |
| } |