114 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
		
		
			
		
	
	
			114 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
|  | /* | ||
|  |  * File      : context_gcc.S | ||
|  |  * This file is part of RT-Thread RTOS | ||
|  |  * COPYRIGHT (C) 2006, RT-Thread Development Team | ||
|  |  * | ||
|  |  * The license and distribution terms for this file may be | ||
|  |  * found in the file LICENSE in this distribution or at | ||
|  |  * http://www.rt-thread.org/license/LICENSE | ||
|  |  * | ||
|  |  * Change Logs: | ||
|  |  * Date           Author       Notes | ||
|  |  * 2006-09-15     QiuYi        The first version | ||
|  |  * 2006-10-09     Bernard      add rt_hw_context_switch_to implementation | ||
|  |  */ | ||
|  | 
 | ||
|  |  /** | ||
|  |  * @addtogroup ia32
 | ||
|  |  */ | ||
|  | /*@{*/ | ||
|  | 
 | ||
|  | /* | ||
|  |  * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
 | ||
|  |  */ | ||
|  | .globl rt_hw_context_switch
 | ||
|  | rt_hw_context_switch: | ||
|  | 	pushfl					/*pushed eflags*/ | ||
|  | /* | ||
|  |  *	add by ssslady@gmail.com 2009-10-14
 | ||
|  |  *      When we return again the esp should no be change. | ||
|  |  * 	The old code change the esp to esp-4 :-(. | ||
|  |  *	A protection fault maybe occure for img created by some compiler,eg.gcc in the fedor-11 | ||
|  |  *      ------------------------------------------------------------------------- | ||
|  |  *	entry			old code			new code | ||
|  |  *	EIP	->return esp	EIP				FLAGS ->return esp | ||
|  |  *	...			FLAGS    ->retern esp		CS | ||
|  |  *				CS				EIP | ||
|  |  *				EIP | ||
|  |  */ | ||
|  | 	popl %eax	/*get flags*/ | ||
|  | 	popl %ebx	/*get eip*/ | ||
|  | 	pushl %eax	/*push flags*/ | ||
|  | 	push %cs	/*push cs*/ | ||
|  | 	pushl %ebx	/*push eip*/ | ||
|  | 	 | ||
|  | /*------------------------------------------------------------------- | ||
|  |  */ | ||
|  | 
 | ||
|  | 	/*push %cs*/				/*push cs register*/ | ||
|  | 	/*pushl 0x8(%esp)*/			/*pushed eip register*/ | ||
|  | 
 | ||
|  | 	pushl $0				/*fill irqno*/ | ||
|  | 	push %ds				/*push ds register*/ | ||
|  | 	push %es				/*push es register*/ | ||
|  | 	pushal					/*push eax,ecx,edx,ebx,esp,ebp,esp,edi registers*/ | ||
|  | 	 | ||
|  | 	/*movl 0x40(%esp), %eax*/	/*to thread TCB*/ | ||
|  | 	/*movl 0x3c(%esp), %ebx*/	/*from thread TCB*/ | ||
|  | 	movl 0x3c(%esp), %eax	/*to thread TCB*/ | ||
|  | 	movl 0x38(%esp), %ebx	/*from thread TCB*/ | ||
|  | 
 | ||
|  | 	movl %esp, (%ebx)		/*store esp in preempted tasks TCB*/ | ||
|  | 	movl (%eax), %esp		/*get new task stack pointer*/ | ||
|  | 
 | ||
|  | 	popal					/*restore new task TCB*/ | ||
|  | 	pop %es | ||
|  | 	pop %ds | ||
|  | 	add $4,%esp				/*skip irqno*/ | ||
|  | 	iret | ||
|  | 
 | ||
|  | /* | ||
|  |  * void rt_hw_context_switch_to(rt_uint32 to);
 | ||
|  |  */ | ||
|  | .globl rt_hw_context_switch_to
 | ||
|  | rt_hw_context_switch_to: | ||
|  | 	push %ebp | ||
|  | 	movl %esp, %ebp | ||
|  | 
 | ||
|  | 	movl 0x8(%ebp), %eax	/* to thread TCB */ | ||
|  | 	movl (%eax), %esp		/* get new task stack pointer */ | ||
|  | 
 | ||
|  | 	popal					/* restore new task TCB*/ | ||
|  | 	pop %es | ||
|  | 	pop %ds | ||
|  | 	add $4, %esp			/* skip irqno */ | ||
|  | 	iret | ||
|  | 
 | ||
|  | /* | ||
|  |  * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
 | ||
|  |  */ | ||
|  | .globl rt_thread_switch_interrupt_flag
 | ||
|  | .globl rt_interrupt_from_thread
 | ||
|  | .globl rt_interrupt_to_thread
 | ||
|  | .globl rt_hw_context_switch_interrupt
 | ||
|  | rt_hw_context_switch_interrupt: | ||
|  | 	pushl %ebp | ||
|  | 	movl %esp, %ebp | ||
|  | 	movl 0xc(%ebp), %eax | ||
|  | 	movl 0x8(%ebp), %ebx | ||
|  | 	 | ||
|  | 	movl $rt_thread_switch_interrupt_flag, %ecx | ||
|  | 	movl (%ecx), %edx | ||
|  | 	cmp $0x1, %edx | ||
|  | 	jz _reswitch | ||
|  | 	 | ||
|  | 	movl $0x1, %edx				/*set rt_thread_switch_interrupt_flag to 1*/ | ||
|  | 	movl %edx, (%ecx) | ||
|  | 	movl $rt_interrupt_from_thread, %edx	/*set rt_interrupt_from_thread*/ | ||
|  | 	movl %ebx, (%edx) | ||
|  | _reswitch: | ||
|  | 	movl $rt_interrupt_to_thread, %edx		/*set rt_interrupt_to_thread*/ | ||
|  | 	movl %eax, (%edx) | ||
|  | 	leave | ||
|  | 	ret |