/****************************************************************************/
/*	Copyright (c) 2009, Bendor Research Pty. Ltd. All rights reserved.		*/
/*	This software is released under the GNU General Public License, version	*/
/*	3, with the exemptions that 1) the header files installed by this 	 	*/
/*	package can be included in closed-source code and 2) the libraries		*/
/*	built by this package can be statically linked into a closed-source 	*/
/*	binary. See the file LICENSE for the details.							*/
/*	This software is provided "AS IS", without any warranty or guarantee.	*/
/*	By using this software you acknowledge that neither Bendor Research nor	*/
/*	any of its personnel or affiliates can be held liable for any damages,	*/
/*	including, but not limited to, loss of business, loss of money, loss of */
/*	life, loss of reputation, arising out of this software being faulty or	*/
/*	not performing as advertised, even if Bendor Research was aware of such	*/
/*	faults in the software. You use this software at your own risk, any and */
/*	all liabilities that arise out of your using this software are strictly	*/
/*	yours.																	*/
/****************************************************************************/

#include <arm_defs.h>
#include <arm_func.h>

/*
*	Context switch
*	~~~~~~~~~~~~~~
*	Entry	R0: the value to return to the new process
*			R1: pointer to the old process's stack pointer
*			R2: pointer to the new process's stack pointer
*			SP: old process stack
*			LR: old process return address
*
*	At entry the interrupt is disabled but we have to enable it before
*	returning to the new process.
*/

	afunc	_bz_context_switch
	stmdb	sp!,{r4-r11,lr}
	str		sp,[r1]
	ldr		sp,[r2]
	ldmia	sp!,{r4-r11,lr}
	mrs		r1,cpsr
	bic		r1,r1,#ARM_IRQDI_MASK
	msr		cpsr,r1
	bx		lr
	.endfunc

/*
*	Start a new process
*	~~~~~~~~~~~~~~~~~~~
*	Entry	R4:	the parameter to pass to the new process
*			R5: the function to start
*			SP: the stack for the new process
*			LR: junk
*/

	afunc	_bz_start
	mov		r0,r4
	bx		r5
	.endfunc

/*
*	Switches from interrupt mode to user mode and starts the first process
*	~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*	Entry	R0:	The first function to start
*			R1:	The stack for the first function
*/

	afunc	_bz_init
	msr		cpsr,#(ARM_IRQDI_MASK|ARM_FIQDI_MASK|ARM_STATE_SYS)
	mov		sp,r1
	bx		r0
	.endfunc

/*
*	Interrupt entry point
*	~~~~~~~~~~~~~~~~~~~~~
*/

	.globl	BZ_IrqEntry
BZ_IrqEntry:
	sub		lr,lr,#4					// Adjust the return address
	stmdb	sp!,{r0-r3,r12,lr}			// Save regs not saved by gcc
	mrs		r0,spsr						// Get the old PSW
	tst		r0,#ARM_IRQDI_MASK			// Is it a stray IRQ?
	ldmneia	sp!,{r0-r3,r12,pc}^			// If yes, restore registers and return
	ldr		r0,state					// Get the kernel state
	ldr		r0,[r0]						// Get address of the handler
	callreg	r0							// Call it
	ldmia	sp!,{r0-r3,r12,pc}^			// Restore registers and return
state:
	.word	_bz_stat

