
.text

/* void arch_enable_ints(void); */
	.global arch_enable_ints
arch_enable_ints:
	mrs	r0, cpsr
	bic	r0, r0, #(1<<7)		/* set the I bit */
	msr	cpsr_c, r0
	bx	lr

/* int arch_disable_ints(void); */
	.global	arch_disable_ints
arch_disable_ints:
	mrs	r1, cpsr
	and	r0, r1, #(1<<7)		/* save the old I bit */
	orr	r1, r1, #(1<<7)
	msr	cpsr_c, r1
	bx	lr

/* int arch_restore_ints(int state); */
	.global	arch_restore_ints
arch_restore_ints:
	mrs	r1, cpsr

	and	r3, r1, #(1<<7)		/* save the old I bit */
	bic	r1, r1, #(1<<7)		/* clear the I bit */

	and	r2, r0, #(1<<7)		/* isolate just the I bit in the input */
	orr	r1, r1, r2		/* set the bit according to input */

	msr	cpsr_c, r1
	mov	r0, r3
	bx	lr

/* int atomic_swap(int *ptr, int val); */
	.global atomic_swap
atomic_swap:
	swp	r0, r2, [r1]
	bx	lr

/* int atomic_add(int *ptr, int val); */
	.global atomic_add
atomic_add:
	/* disable interrupts, do the add, and reenable */
	mrs	r2, cpsr
	mov	r12, r2
	orr	r2, r2, #(3<<6)
	msr	cpsr_c, r2

	/* ints disabled, old cpsr state in r12 */
	
	/* do the add, leave the previous value in r0 */
	mov	r3, r0
	ldr	r0, [r3]
	add	r2, r0, r1
	str	r2, [r3]

	/* restore interrupts and exit */
	msr	cpsr_c, r12
	bx	lr
	
/* int atomic_and(int *ptr, int val); */
	.global atomic_and
atomic_and:
	/* disable interrupts, do the and, and reenable */
	mrs	r2, cpsr
	mov	r12, r2
	orr	r2, r2, #(3<<6)
	msr	cpsr_c, r2

	/* ints disabled, old cpsr state in r12 */
	
	/* do the and, leave the previous value in r0 */
	mov	r3, r0
	ldr	r0, [r3]
	and	r2, r0, r1
	str	r2, [r3]

	/* restore interrupts and exit */
	msr	cpsr_c, r12
	bx	lr
	
/* int atomic_or(int *ptr, int val); */
	.global atomic_or
atomic_or:
	/* disable interrupts, do the or, and reenable */
	mrs	r2, cpsr
	mov	r12, r2
	orr	r2, r2, #(3<<6)
	msr	cpsr_c, r2

	/* ints disabled, old cpsr state in r12 */
	
	/* do the or, leave the previous value in r0 */
	mov	r3, r0
	ldr	r0, [r3]
	orr	r2, r0, r1
	str	r2, [r3]

	/* restore interrupts and exit */
	msr	cpsr_c, r12
	bx	lr

/* void arch_flush_i_cache(void); */
	.global arch_flush_i_cache
arch_flush_i_cache:
	bx	lr

/* void arch_flush_d_cache(void); */
	.global arch_flush_d_cache
arch_flush_d_cache:
	bx	lr

/* void arch_idle(); */
	.global arch_idle
arch_idle:
	bx	lr
