use the -newos toolchain even if -elf is present.
[newos.git] / kernel / arch / i386 / arch_i386.S
blob64482f3c8864978a2b56ed10c6a58c1569299031
1 /*
2 ** Copyright 2001, Travis Geiselbrecht. All rights reserved.
3 ** Copyright 2002, Michael Noisternig. All rights reserved.
4 ** Distributed under the terms of the NewOS License.
5 */
7 #define FUNCTION(x) .global x; .type x,@function; x
9 .text
11 /* int atomic_add(int *val, int incr) */
12 FUNCTION(atomic_add):
13         movl    4(%esp),%edx
14         movl    8(%esp),%eax
15         lock
16         xaddl   %eax,(%edx)
17         ret
19 /* int atomic_and(int *val, int incr) */
20 FUNCTION(atomic_and):
21         movl    4(%esp),%edx
23 _atomic_and1:
24         movl    8(%esp),%ecx
25         movl    (%edx),%eax
26         andl    %eax,%ecx
28         lock
29         cmpxchgl        %ecx,(%edx)
31         jnz             _atomic_and1
33         ret
35 /* int atomic_or(int *val, int incr) */
36 FUNCTION(atomic_or):
37         movl    4(%esp),%edx
39 _atomic_or1:
40         movl    8(%esp),%ecx
41         movl    (%edx),%eax
42         orl             %eax,%ecx
44         lock
45         cmpxchgl        %ecx,(%edx)
47         jnz             _atomic_or1
49         ret
51 /* int atomic_set(int *val, int set_to) */
52 FUNCTION(atomic_set):
53         movl    4(%esp),%edx
54         movl    8(%esp),%eax
55         xchg    %eax,(%edx)
56         ret
58 /* int test_and_set(int *val, int set_to, int test_val) */
59 FUNCTION(test_and_set):
60         movl    4(%esp),%edx
61         movl    8(%esp),%ecx
62         movl    12(%esp),%eax
64         lock
65         cmpxchgl        %ecx,(%edx)
67         ret
69 /* uint64 i386_rdtsc() */
70 .global i386_rdtsc
71 i386_rdtsc:
72         rdtsc
73         ret
75 /* saves the conversion factor needed for system_time */
76 .global cv_factor
77 cv_factor:
78         .word 0
80 FUNCTION(setup_system_time):
81         movl    4(%esp),%eax
82         movl    %eax,cv_factor
83         ret
85 /* bigtime_t i386_cycles_to_time(uint64 cycles); */
86 FUNCTION(i386_cycles_to_time):
87         movl    4(%esp),%eax
88         movl    8(%esp),%edx
90         pushl   %ebx
91         pushl   %ecx
92         movl    cv_factor, %ebx
93         movl    %edx, %ecx      /* save high half */
94         mull    %ebx            /* truncate %eax, but keep %edx */
95         movl    %ecx, %eax
96         movl    %edx, %ecx      /* save high half of low */
97         mull    %ebx /*, %eax*/
98         /* now compute  [%edx, %eax] + [%ecx], propagating carry */
99         subl    %ebx, %ebx      /* need zero to propagate carry */
100         addl    %ecx, %eax
101         adc             %ebx, %edx
102         popl    %ecx
103         popl    %ebx
104         ret
106 /* void i386_set_task_switched(void); */
107 FUNCTION(i386_set_task_switched):
108         movl    %cr0,%eax
109         or              $0x4,%eax
110         movl    %eax,%cr0
111         ret
113 /* void i386_clear_task_switched(void); */
114 FUNCTION(i386_clear_task_switched):
115         movl    %cr0,%eax
116         and             $0xfffffffb,%eax
117         movl    %eax,%cr0
118         ret
120 /* void arch_cpu_global_TLB_invalidate(); */
121 FUNCTION(arch_cpu_global_TLB_invalidate):
122         movl    %cr3,%eax
123         movl    %eax,%cr3
124         ret
126 /* void i386_fsave(void *fpu_state); */
127 FUNCTION(i386_fsave):
128         movl    4(%esp), %eax
129         fsave   (%eax)
130         ret
132 /* void i386_fxsave(void *fpu_state); */
133 FUNCTION(i386_fxsave):
134         movl    4(%esp), %eax
135         fxsave  (%eax)
136         ret
138 /* void i386_frstor(void *fpu_state); */
139 FUNCTION(i386_frstor):
140         movl    4(%esp), %eax
141         frstor  (%eax)
142         ret
144 /* void i386_fxrstor(void *fpu_state); */
145 FUNCTION(i386_fxrstor):
146         movl    4(%esp), %eax
147         fxrstor (%eax)
148         ret
150 /* void i386_fsave_swap(void *old_fpu_state, void *new_fpu_state); */
151 FUNCTION(i386_fsave_swap):
152         movl    4(%esp),%eax
153         fsave   (%eax)
154         movl    8(%esp),%eax
155         frstor  (%eax)
156         ret
158 /* void i386_fxsave_swap(void *old_fpu_state, void *new_fpu_state); */
159 FUNCTION(i386_fxsave_swap):
160         movl    4(%esp),%eax
161         fxsave  (%eax)
162         movl    8(%esp),%eax
163         fxrstor (%eax)
164         ret
166 /* void i386_cpuid(unsigned int selector, unsigned int *data); */
167 FUNCTION(i386_cpuid):
168         pushl   %ebx
169         pushl   %edi
170         movl    12(%esp),%eax
171         movl    16(%esp),%edi
172         cpuid
173         movl    %eax,0(%edi)
174         movl    %ebx,4(%edi)
175         movl    %ecx,8(%edi)
176         movl    %edx,12(%edi)
177         popl    %edi
178         popl    %ebx
179         ret
181 /* void i386_context_switch(struct arch_thread *old, struct arch_thread *new); */
182 FUNCTION(i386_context_switch):
183         pusha                                   /* pushes 8 words onto the stack */
185         movl    36(%esp),%eax   /* save current_stack */
186         movl    %esp,(%eax)
188         pushl   %ss                             /* push the old ss */
189         popl    %edx                    /* pop it back off the stack */
190         movl    %edx,4(%eax)    /* save it into the arch_thread structure */
192         movl    40(%esp),%eax   /* get new current_stack */
193         lss             (%eax),%esp
195         popa
196         ret
198 /* void i386_swap_pgdir(addr_t new_pgdir); */
199 FUNCTION(i386_swap_pgdir):
200         movl    4(%esp),%eax
201         movl    %eax,%cr3
202         ret
204 /* thread exit stub */
205         .align 4
206 i386_uspace_exit_stub:
207         pushl   %eax
208         movl    $1, %ecx
209         lea     (%esp), %edx
210         movl    $25, %eax;
211         int     $99
212         .align 4
213 i386_uspace_exit_stub_end:
216 /* void i386_enter_uspace(addr_t entry, void *args, addr_t ustack_top); */
217 FUNCTION(i386_enter_uspace):
218         movl    4(%esp),%eax    // get entry point
219         movl    8(%esp),%edx    // get arguments
220         movl    12(%esp),%ebx   // get user stack
221         movw    $0x23,%cx
222         movw    %cx,%ds
223         movw    %cx,%es
224         movw    %cx,%fs
225         movw    %cx,%gs
227         // copy exit stub to stack
228         movl    $i386_uspace_exit_stub_end, %esi
229 _copy_more:
230         lea     -4(%esi), %esi
231         lea     -4(%ebx), %ebx
232         mov     (%esi), %ecx
233         mov     %ecx, (%ebx)
234         cmp     $i386_uspace_exit_stub, %esi
235         jg      _copy_more
238         // push the args onto the user stack
239         movl    %edx,-4(%ebx)   // args
240         movl    %ebx,-8(%ebx)   // fake return address to copied exit stub
241         sub             $8,%ebx
243         pushl   $0x23                   // user data segment
244         pushl   %ebx                    // user stack
245         pushl   $(1 << 9) | 2   // user flags
246         pushl   $0x1b                   // user code segment
247         pushl   %eax                    // user IP
248         iret
250 /* void i386_switch_stack_and_call(addr_t stack, void (*func)(void *), void *arg); */
251 FUNCTION(i386_switch_stack_and_call):
252         movl    4(%esp),%eax    // new stack
253         movl    8(%esp),%ecx    // func
254         movl    12(%esp),%edx   // args
256         movl    %eax,%esp               // switch the stack
257         pushl   %edx                    // push the argument
258         call    *%ecx                   // call the target function
259 _loop:
260         jmp             _loop
262 null_idt_descr:
263         .word   0
264         .word   0,0
266 FUNCTION(reboot):
267         lidt    null_idt_descr
268         int             $0
269 done:
270         jmp             done
273 FUNCTION(dbg_save_registers):
274         pushl   %esi
275         pushl   %eax
276         movl    12(%esp), %esi
278         movl    %eax, 0(%esi)
279         movl    %ebx, 4(%esi)
280         movl    %ecx, 8(%esi)
281         movl    %edx, 12(%esi)
283         lea     16(%esp), %eax
284         movl    %eax, 16(%esi)  // caller's %esp
285         movl    %ebp, 20(%esi)
287         movl    4(%esp), %eax
288         movl    %eax, 24(%esi)  // caller's %esi
289         movl    %edi, 28(%esi)
291         movl    8(%esp), %eax
292         movl    %eax, 32(%esi)  // caller's %ebp
295         pushfl
296         popl    %eax
297         mov     %eax, 36(%esi)
299         movl    %cs, 40(%esi)
300         movl    %ss, 44(%esi)
301         movl    %ds, 48(%esi)
302         movl    %es, 52(%esi)
304         popl    %eax
305         popl    %esi
306         ret