134 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
			
		
		
	
	
			134 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
| /*
 | |
| 
 | |
| Copyright (c) 2005 Red Hat Incorporated.
 | |
| All rights reserved.
 | |
| 
 | |
| Redistribution and use in source and binary forms, with or without 
 | |
| modification, are permitted provided that the following conditions are met: 
 | |
| 
 | |
|     Redistributions of source code must retain the above copyright 
 | |
|     notice, this list of conditions and the following disclaimer.
 | |
| 
 | |
|     Redistributions in binary form must reproduce the above copyright
 | |
|     notice, this list of conditions and the following disclaimer in the
 | |
|     documentation and/or other materials provided with the distribution.
 | |
| 
 | |
|     The name of Red Hat Incorporated may not be used to endorse 
 | |
|     or promote products derived from this software without specific 
 | |
|     prior written permission.
 | |
| 
 | |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND 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 RED HAT INCORPORATED 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. 
 | |
| 
 | |
| */
 | |
| 
 | |
| #if defined(__r8c_cpu__) || defined(__m16c_cpu__)
 | |
| #define A16 1
 | |
| #endif
 | |
| 
 | |
| /* We implement setjmp/longjmp much like the way gcc implements
 | |
|    exceptions - we create new stack frames, then switch to them and
 | |
|    return.  Thus, the two setjmp's below each push all the relevent
 | |
|    registers, then copy the whole frame into the buffer (first $sp is
 | |
|    moved, then smovf copies the frame itself), and the two longjmps
 | |
|    restore $sp, copy the frame back into place, and issue the same
 | |
|    return as the setjmp would have used.
 | |
| 
 | |
|    Since the sizes of registers differs between the 16 and 24 bit
 | |
|    models, we provide separate implementations for each rather than
 | |
|    trying to parameterize them.
 | |
| 
 | |
|    Jump buffer sizes: 21 bytes for 16 bit, 34 bytes for 24 bit.
 | |
| */
 | |
| 
 | |
| 	.text
 | |
| 
 | |
| #ifdef A16	/* 16 bit versions */
 | |
| 
 | |
| 	.global	_setjmp
 | |
| _setjmp:
 | |
| 	enter	#0
 | |
| 	pushm	r1,r2,r3,a0,a1,sb,fb
 | |
| 
 | |
| ; At this point, the stack looks like this:
 | |
| ; ... [pc:3] [oldfb:2] <fb> [r1:2] [r2:2] [r3:2] [a0:2] [a1:2] [sb:2] [fb:2] <sp> */
 | |
| 
 | |
| 	mov.w	r1,a1		;  a1 is the destination of smovf
 | |
| 	mov.b	#0,r1h
 | |
| 	stc	sp,a0		;  r1h:a0 is the source of smovf
 | |
| 	mov.w	a0,[a1]
 | |
| 	add.w	#2,a1
 | |
| 	mov.w	#19,r3		;  plus two for sp later
 | |
| 	smovf.b
 | |
| 
 | |
| 	; Return 0 to caller.
 | |
| 	mov.w	#0,r0
 | |
| 	popm	r1,r2,r3,a0,a1,sb,fb
 | |
| 	exitd
 | |
| 
 | |
| 	.global	_longjmp
 | |
| _longjmp:
 | |
| 	enter	#0
 | |
| 	mov.w	r1,a0		;  pointer to jump buf
 | |
| 	mov.w	r2,r0		;  setjmp's "new" return value
 | |
| 
 | |
| 	mov.b	#0,r1h		;  r1h:	a0 is the source, now jmpbuf
 | |
| 	mov.w	[a0],a1		;  dest is new stack
 | |
| 	ldc	a1,sp
 | |
| 	add.w	#2,a0
 | |
| 	mov.w	#19,r3
 | |
| 	smovf.b
 | |
| 
 | |
| 	;; now return to our caller with this newly restored frame
 | |
| 	popm	r1,r2,r3,a0,a1,sb,fb
 | |
| 	exitd
 | |
| 
 | |
| #else	/* 24 bit versions */
 | |
| 
 | |
| 	.global	_setjmp
 | |
| _setjmp:
 | |
| 	enter	#0
 | |
| 	pushm	r1,r2,r3,a0,a1,sb,fb
 | |
| 
 | |
| ; At this point, the stack looks like this:
 | |
| ; ... [jbuf:4] [pc:4] [oldfb:4] <fb> [r1:2] [r2:2] [r3:2] [a0:4] [a1:4] [sb:4] [fb:4] <sp> */
 | |
| 
 | |
| 	mov.l	8[fb],a1	;  a1 is the destination of smovf
 | |
| 	stc	sp,a0		;  r1h:a0 is the source of smovf
 | |
| 	mov.l	a0,[a1]
 | |
| 	add.l	#4,a1
 | |
| 	mov.w	#30,r3		;  plus two for sp later
 | |
| 	smovf.b
 | |
| 
 | |
| 	; Return 0 to caller.
 | |
| 	mov.w	#0,r0
 | |
| 	popm	r1,r2,r3,a0,a1,sb,fb
 | |
| 	exitd
 | |
| 
 | |
| 	.global	_longjmp
 | |
| _longjmp:
 | |
| 	enter	#0
 | |
| ; ... [rv:2] [jbuf:4] [pc:4] [oldfb:4] <fb>
 | |
| 	mov.l	8[fb],a0	;  pointer to jump buf
 | |
| 	mov.w	12[fb],r0	;  setjmp's "new" return value
 | |
| 
 | |
| 	mov.l	[a0],a1		;  dest is new stack
 | |
| 	ldc	a1,sp
 | |
| 	add.l	#4,a0
 | |
| 	mov.w	#30,r3
 | |
| 	smovf.b
 | |
| 
 | |
| 	;; now return to our caller with this newly restored frame
 | |
| 	popm	r1,r2,r3,a0,a1,sb,fb
 | |
| 	exitd
 | |
| #endif
 | |
| 
 |