xref: /nrf52832-nimble/rt-thread/libcpu/ia32/context_gcc.S (revision 104654410c56c573564690304ae786df310c91fc)
1*10465441SEvalZero/*
2*10465441SEvalZero * File      : context_gcc.S
3*10465441SEvalZero * This file is part of RT-Thread RTOS
4*10465441SEvalZero * COPYRIGHT (C) 2006, RT-Thread Development Team
5*10465441SEvalZero *
6*10465441SEvalZero * The license and distribution terms for this file may be
7*10465441SEvalZero * found in the file LICENSE in this distribution or at
8*10465441SEvalZero * http://www.rt-thread.org/license/LICENSE
9*10465441SEvalZero *
10*10465441SEvalZero * Change Logs:
11*10465441SEvalZero * Date           Author       Notes
12*10465441SEvalZero * 2006-09-15     QiuYi        The first version
13*10465441SEvalZero * 2006-10-09     Bernard      add rt_hw_context_switch_to implementation
14*10465441SEvalZero */
15*10465441SEvalZero
16*10465441SEvalZero /**
17*10465441SEvalZero * @addtogroup ia32
18*10465441SEvalZero */
19*10465441SEvalZero/*@{*/
20*10465441SEvalZero
21*10465441SEvalZero/*
22*10465441SEvalZero * void rt_hw_context_switch(rt_uint32 from, rt_uint32 to);
23*10465441SEvalZero */
24*10465441SEvalZero.globl rt_hw_context_switch
25*10465441SEvalZerort_hw_context_switch:
26*10465441SEvalZero	pushfl					/*pushed eflags*/
27*10465441SEvalZero/*
28*10465441SEvalZero *	add by [email protected] 2009-10-14
29*10465441SEvalZero *      When we return again the esp should no be change.
30*10465441SEvalZero * 	The old code change the esp to esp-4 :-(.
31*10465441SEvalZero *	A protection fault maybe occure for img created by some compiler,eg.gcc in the fedor-11
32*10465441SEvalZero *      -------------------------------------------------------------------------
33*10465441SEvalZero *	entry			old code			new code
34*10465441SEvalZero *	EIP	->return esp	EIP				FLAGS ->return esp
35*10465441SEvalZero *	...			FLAGS    ->retern esp		CS
36*10465441SEvalZero *				CS				EIP
37*10465441SEvalZero *				EIP
38*10465441SEvalZero */
39*10465441SEvalZero	popl %eax	/*get flags*/
40*10465441SEvalZero	popl %ebx	/*get eip*/
41*10465441SEvalZero	pushl %eax	/*push flags*/
42*10465441SEvalZero	push %cs	/*push cs*/
43*10465441SEvalZero	pushl %ebx	/*push eip*/
44*10465441SEvalZero
45*10465441SEvalZero/*-------------------------------------------------------------------
46*10465441SEvalZero */
47*10465441SEvalZero
48*10465441SEvalZero	/*push %cs*/				/*push cs register*/
49*10465441SEvalZero	/*pushl 0x8(%esp)*/			/*pushed eip register*/
50*10465441SEvalZero
51*10465441SEvalZero	pushl $0				/*fill irqno*/
52*10465441SEvalZero	push %ds				/*push ds register*/
53*10465441SEvalZero	push %es				/*push es register*/
54*10465441SEvalZero	pushal					/*push eax,ecx,edx,ebx,esp,ebp,esp,edi registers*/
55*10465441SEvalZero
56*10465441SEvalZero	/*movl 0x40(%esp), %eax*/	/*to thread TCB*/
57*10465441SEvalZero	/*movl 0x3c(%esp), %ebx*/	/*from thread TCB*/
58*10465441SEvalZero	movl 0x3c(%esp), %eax	/*to thread TCB*/
59*10465441SEvalZero	movl 0x38(%esp), %ebx	/*from thread TCB*/
60*10465441SEvalZero
61*10465441SEvalZero	movl %esp, (%ebx)		/*store esp in preempted tasks TCB*/
62*10465441SEvalZero	movl (%eax), %esp		/*get new task stack pointer*/
63*10465441SEvalZero
64*10465441SEvalZero	popal					/*restore new task TCB*/
65*10465441SEvalZero	pop %es
66*10465441SEvalZero	pop %ds
67*10465441SEvalZero	add $4,%esp				/*skip irqno*/
68*10465441SEvalZero	iret
69*10465441SEvalZero
70*10465441SEvalZero/*
71*10465441SEvalZero * void rt_hw_context_switch_to(rt_uint32 to);
72*10465441SEvalZero */
73*10465441SEvalZero.globl rt_hw_context_switch_to
74*10465441SEvalZerort_hw_context_switch_to:
75*10465441SEvalZero	push %ebp
76*10465441SEvalZero	movl %esp, %ebp
77*10465441SEvalZero
78*10465441SEvalZero	movl 0x8(%ebp), %eax	/* to thread TCB */
79*10465441SEvalZero	movl (%eax), %esp		/* get new task stack pointer */
80*10465441SEvalZero
81*10465441SEvalZero	popal					/* restore new task TCB*/
82*10465441SEvalZero	pop %es
83*10465441SEvalZero	pop %ds
84*10465441SEvalZero	add $4, %esp			/* skip irqno */
85*10465441SEvalZero	iret
86*10465441SEvalZero
87*10465441SEvalZero/*
88*10465441SEvalZero * void rt_hw_context_switch_interrupt(rt_uint32 from, rt_uint32 to);
89*10465441SEvalZero */
90*10465441SEvalZero.globl rt_thread_switch_interrupt_flag
91*10465441SEvalZero.globl rt_interrupt_from_thread
92*10465441SEvalZero.globl rt_interrupt_to_thread
93*10465441SEvalZero.globl rt_hw_context_switch_interrupt
94*10465441SEvalZerort_hw_context_switch_interrupt:
95*10465441SEvalZero	pushl %ebp
96*10465441SEvalZero	movl %esp, %ebp
97*10465441SEvalZero	movl 0xc(%ebp), %eax
98*10465441SEvalZero	movl 0x8(%ebp), %ebx
99*10465441SEvalZero
100*10465441SEvalZero	movl $rt_thread_switch_interrupt_flag, %ecx
101*10465441SEvalZero	movl (%ecx), %edx
102*10465441SEvalZero	cmp $0x1, %edx
103*10465441SEvalZero	jz _reswitch
104*10465441SEvalZero
105*10465441SEvalZero	movl $0x1, %edx				/*set rt_thread_switch_interrupt_flag to 1*/
106*10465441SEvalZero	movl %edx, (%ecx)
107*10465441SEvalZero	movl $rt_interrupt_from_thread, %edx	/*set rt_interrupt_from_thread*/
108*10465441SEvalZero	movl %ebx, (%edx)
109*10465441SEvalZero_reswitch:
110*10465441SEvalZero	movl $rt_interrupt_to_thread, %edx		/*set rt_interrupt_to_thread*/
111*10465441SEvalZero	movl %eax, (%edx)
112*10465441SEvalZero	leave
113*10465441SEvalZero	ret
114