90 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
			
		
		
	
	
			90 lines
		
	
	
		
			1.9 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
# setjmp/longjmp for Renesas RX.
 | 
						|
# 
 | 
						|
# The jmpbuf looks like this:
 | 
						|
#	
 | 
						|
# Register	jmpbuf offset
 | 
						|
# R0		0x0
 | 
						|
# R1		0x4
 | 
						|
# R2		0x8
 | 
						|
# R3		0xc
 | 
						|
# R4		0x10
 | 
						|
# R5		0x14
 | 
						|
# R6		0x18
 | 
						|
# R7		0x1c
 | 
						|
# R8		0x20
 | 
						|
# R9		0x24
 | 
						|
# R10		0x28
 | 
						|
# R11		0x2c
 | 
						|
# R12		0x30
 | 
						|
# R13		0x34
 | 
						|
# R14		0x38
 | 
						|
# R15		0x3c
 | 
						|
# PC		0x40
 | 
						|
#
 | 
						|
# R1 contains the pointer to jmpbuf:
 | 
						|
#
 | 
						|
#	int R1 = setjmp (jmp_buf R1)
 | 
						|
#	void longjmp (jmp_buf R1, int R2)
 | 
						|
#
 | 
						|
# The ABI allows for R1-R5 to be clobbered by functions.  We must be
 | 
						|
# careful to always leave the stack in a usable state in case an
 | 
						|
# interrupt happens.
 | 
						|
 | 
						|
	.text
 | 
						|
	.global	_setjmp
 | 
						|
	.type	_setjmp, @function
 | 
						|
_setjmp:
 | 
						|
	mov.l	r0, [r1]	; save all the general registers
 | 
						|
	mov.l	r1, 0x4[r1]	; longjmp won't use this, but someone else might.
 | 
						|
	mov.l	r2, 0x8[r1]
 | 
						|
	mov.l	r3, 0xc[r1]
 | 
						|
	mov.l	r4, 0x10[r1]
 | 
						|
	mov.l	r5, 0x14[r1]
 | 
						|
	mov.l	r6, 0x18[r1]
 | 
						|
	mov.l	r7, 0x1c[r1]
 | 
						|
	mov.l	r8, 0x20[r1]
 | 
						|
	mov.l	r9, 0x24[r1]
 | 
						|
	mov.l	r10, 0x28[r1]
 | 
						|
	mov.l	r11, 0x2c[r1]
 | 
						|
	mov.l	r12, 0x30[r1]
 | 
						|
	mov.l	r13, 0x34[r1]
 | 
						|
	mov.l	r14, 0x38[r1]
 | 
						|
	mov.l	r15, 0x3c[r1]
 | 
						|
	mov.l	[r0], r2	; get return address off the stack
 | 
						|
	mov.l	r2, 0x40[r1]	; PC
 | 
						|
	mov	#0, r1		; Return 0.
 | 
						|
	rts
 | 
						|
.Lend1:
 | 
						|
	.size	_setjmp, .Lend1 - _setjmp
 | 
						|
 | 
						|
 | 
						|
	.global	_longjmp
 | 
						|
	.type	_longjmp, @function
 | 
						|
_longjmp:
 | 
						|
	tst	r2, r2		; Set the Z flag if r2 is 0.
 | 
						|
	stz	#1, r2		; If the Z flag was set put 1 into the return register.
 | 
						|
	mov	r2, 4[r1]	; Put r2 (our return value) into the setjmp buffer as r1.
 | 
						|
 | 
						|
	mov.l	[r1], r0	; Restore the stack - there's a slot for PC
 | 
						|
	mov.l	0x40[r1], r2	; Get the saved PC
 | 
						|
	mov.l	r2, [r0]	; Overwrite the old return address
 | 
						|
 | 
						|
	mov.l	0x3c[r1], r15
 | 
						|
	mov.l	0x38[r1], r14
 | 
						|
	mov.l	0x34[r1], r13
 | 
						|
	mov.l	0x30[r1], r12
 | 
						|
	mov.l	0x2c[r1], r11
 | 
						|
	mov.l	0x28[r1], r10
 | 
						|
	mov.l	0x24[r1], r9
 | 
						|
	mov.l	0x20[r1], r8
 | 
						|
	mov.l	0x1c[r1], r7
 | 
						|
	mov.l	0x18[r1], r6
 | 
						|
	mov.l	0x14[r1], r5
 | 
						|
	mov.l	0x10[r1], r4
 | 
						|
	mov.l	0xc[r1], r3
 | 
						|
	mov.l	0x8[r1], r2
 | 
						|
	mov.l	0x4[r1], r1	; This sets up the new return value
 | 
						|
	rts
 | 
						|
.Lend2:
 | 
						|
	.size	_longjmp, .Lend2 - _longjmp
 |