]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/cddl/dev/dtrace/i386/dtrace_asm.S
Merge clang trunk r338150 (just before the 7.0.0 branch point), and
[FreeBSD/FreeBSD.git] / sys / cddl / dev / dtrace / i386 / dtrace_asm.S
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  *
22  * $FreeBSD$
23  */
24 /*
25  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
26  * Use is subject to license terms.
27  */
28
29 #define _ASM
30
31 #include <machine/asmacros.h>
32 #include <sys/cpuvar_defs.h>
33 #include <sys/dtrace.h>
34
35 #include "assym.inc"
36
37         ENTRY(dtrace_invop_start)
38
39         pushl   %eax                    /* push %eax -- may be return value */
40         pushl   %esp                    /* push stack pointer */
41         subl    $8, (%esp)              /* skip first arg and segment regs */
42         pushl   40(%esp)                /* push calling EIP */
43
44         /*
45          * Call dtrace_invop to let it check if the exception was
46          * a fbt one. The return value in %eax will tell us what
47          * dtrace_invop wants us to do.
48          */
49         call    dtrace_invop
50         ALTENTRY(dtrace_invop_callsite)
51         addl    $12, %esp
52         cmpl    $DTRACE_INVOP_PUSHL_EBP, %eax
53         je      invop_push
54         cmpl    $DTRACE_INVOP_POPL_EBP, %eax
55         je      invop_pop
56         cmpl    $DTRACE_INVOP_LEAVE, %eax
57         je      invop_leave
58         cmpl    $DTRACE_INVOP_NOP, %eax
59         je      invop_nop
60
61         /* When all else fails handle the trap in the usual way. */
62         jmpl    *dtrace_invop_calltrap_addr
63
64 invop_push:
65         /*
66          * We must emulate a "pushl %ebp".  To do this, we pull the stack
67          * down 4 bytes, and then store the base pointer.
68          */
69         popal
70         subl    $4, %esp                /* make room for %ebp */
71         pushl   %eax                    /* push temp */
72         movl    8(%esp), %eax           /* load calling EIP */
73         incl    %eax                    /* increment over LOCK prefix */
74         movl    %eax, 4(%esp)           /* store calling EIP */
75         movl    12(%esp), %eax          /* load calling CS */
76         movl    %eax, 8(%esp)           /* store calling CS */
77         movl    16(%esp), %eax          /* load calling EFLAGS */
78         movl    %eax, 12(%esp)          /* store calling EFLAGS */
79         movl    %ebp, 16(%esp)          /* push %ebp */
80         popl    %eax                    /* pop off temp */
81         iret                            /* Return from interrupt. */
82 invop_pop:
83         /*
84          * We must emulate a "popl %ebp".  To do this, we do the opposite of
85          * the above:  we remove the %ebp from the stack, and squeeze up the
86          * saved state from the trap.
87          */
88         popal
89         pushl   %eax                    /* push temp */
90         movl    16(%esp), %ebp          /* pop %ebp */
91         movl    12(%esp), %eax          /* load calling EFLAGS */
92         movl    %eax, 16(%esp)          /* store calling EFLAGS */
93         movl    8(%esp), %eax           /* load calling CS */
94         movl    %eax, 12(%esp)          /* store calling CS */
95         movl    4(%esp), %eax           /* load calling EIP */
96         incl    %eax                    /* increment over LOCK prefix */
97         movl    %eax, 8(%esp)           /* store calling EIP */
98         popl    %eax                    /* pop off temp */
99         addl    $4, %esp                /* adjust stack pointer */
100         iret                            /* Return from interrupt. */
101 invop_leave:
102         /*
103          * We must emulate a "leave", which is the same as a "movl %ebp, %esp"
104          * followed by a "popl %ebp".  This looks similar to the above, but
105          * requires two temporaries:  one for the new base pointer, and one
106          * for the staging register.
107          */
108         popa
109         pushl   %eax                    /* push temp */
110         pushl   %ebx                    /* push temp */
111         movl    %ebp, %ebx              /* set temp to old %ebp */
112         movl    (%ebx), %ebp            /* pop %ebp */
113         movl    16(%esp), %eax          /* load calling EFLAGS */
114         movl    %eax, (%ebx)            /* store calling EFLAGS */
115         movl    12(%esp), %eax          /* load calling CS */
116         movl    %eax, -4(%ebx)          /* store calling CS */
117         movl    8(%esp), %eax           /* load calling EIP */
118         incl    %eax                    /* increment over LOCK prefix */
119         movl    %eax, -8(%ebx)          /* store calling EIP */
120         subl    $8, %ebx                /* adjust for three pushes, one pop */
121         movl    %ebx, 8(%esp)           /* temporarily store new %esp */
122         popl    %ebx                    /* pop off temp */
123         popl    %eax                    /* pop off temp */
124         movl    (%esp), %esp            /* set stack pointer */
125         iret                            /* return from interrupt */
126 invop_nop:
127         /*
128          * We must emulate a "nop".  This is obviously not hard:  we need only
129          * advance the %eip by one.
130          */
131         popa
132         incl    (%esp)
133         iret                            /* return from interrupt */
134
135         END(dtrace_invop_start)
136
137 /*
138 void dtrace_invop_init(void)
139 */
140         ENTRY(dtrace_invop_init)
141         movl    $dtrace_invop_start, dtrace_invop_jump_addr
142         ret
143         END(dtrace_invop_init)
144
145 /*
146 void dtrace_invop_uninit(void)
147 */
148         ENTRY(dtrace_invop_uninit)
149         movl    $0, dtrace_invop_jump_addr
150         ret
151         END(dtrace_invop_uninit)
152
153 /*
154 greg_t dtrace_getfp(void)
155 */
156
157         ENTRY(dtrace_getfp)
158         movl    %ebp, %eax
159         ret
160         END(dtrace_getfp)
161
162 /*
163 uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)
164 */
165
166         ENTRY(dtrace_cas32)
167         ALTENTRY(dtrace_casptr)
168         movl    4(%esp), %edx
169         movl    8(%esp), %eax
170         movl    12(%esp), %ecx
171         lock
172         cmpxchgl %ecx, (%edx)
173         ret
174         END(dtrace_casptr)
175         END(dtrace_cas32)
176
177 /*
178 uintptr_t dtrace_caller(int aframes)
179 */
180
181         ENTRY(dtrace_caller)
182         movl    $-1, %eax
183         ret
184         END(dtrace_caller)
185
186 /*
187 void dtrace_copy(uintptr_t src, uintptr_t dest, size_t size)
188 */
189
190         ENTRY(dtrace_copy)
191         pushl   %ebp
192         movl    %esp, %ebp
193         pushl   %esi
194         pushl   %edi
195
196         movl    8(%ebp), %esi           /* Load source address */
197         movl    12(%ebp), %edi          /* Load destination address */
198         movl    16(%ebp), %ecx          /* Load count */
199         repz                            /* Repeat for count... */
200         smovb                           /*   move from %ds:si to %es:di */
201
202         popl    %edi
203         popl    %esi
204         movl    %ebp, %esp
205         popl    %ebp
206         ret
207         END(dtrace_copy)
208
209 /*
210 void dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size)
211 */
212
213         ENTRY(dtrace_copystr)
214
215         pushl   %ebp                    /* Setup stack frame */
216         movl    %esp, %ebp
217         pushl   %ebx                    /* Save registers */
218
219         movl    8(%ebp), %ebx           /* Load source address */
220         movl    12(%ebp), %edx          /* Load destination address */
221         movl    16(%ebp), %ecx          /* Load count */
222
223 0:
224         movb    (%ebx), %al             /* Load from source */
225         movb    %al, (%edx)             /* Store to destination */
226         incl    %ebx                    /* Increment source pointer */
227         incl    %edx                    /* Increment destination pointer */
228         decl    %ecx                    /* Decrement remaining count */
229         cmpb    $0, %al
230         je      1f
231         cmpl    $0, %ecx
232         jne     0b
233
234 1:
235         popl    %ebx
236         movl    %ebp, %esp
237         popl    %ebp
238         ret
239
240         END(dtrace_copystr)
241
242 /*
243 uintptr_t dtrace_fulword(void *addr)
244 */
245
246         ENTRY(dtrace_fulword)
247         movl    4(%esp), %ecx
248         xorl    %eax, %eax
249         movl    (%ecx), %eax
250         ret
251         END(dtrace_fulword)
252
253 /*
254 uint8_t dtrace_fuword8_nocheck(void *addr)
255 */
256
257         ENTRY(dtrace_fuword8_nocheck)
258         movl    4(%esp), %ecx
259         xorl    %eax, %eax
260         movzbl  (%ecx), %eax
261         ret
262         END(dtrace_fuword8_nocheck)
263
264 /*
265 uint16_t dtrace_fuword16_nocheck(void *addr)
266 */
267
268         ENTRY(dtrace_fuword16_nocheck)
269         movl    4(%esp), %ecx
270         xorl    %eax, %eax
271         movzwl  (%ecx), %eax
272         ret
273         END(dtrace_fuword16_nocheck)
274
275 /*
276 uint32_t dtrace_fuword32_nocheck(void *addr)
277 */
278
279         ENTRY(dtrace_fuword32_nocheck)
280         movl    4(%esp), %ecx
281         xorl    %eax, %eax
282         movl    (%ecx), %eax
283         ret
284         END(dtrace_fuword32_nocheck)
285
286 /*
287 uint64_t dtrace_fuword64_nocheck(void *addr)
288 */
289
290         ENTRY(dtrace_fuword64_nocheck)
291         movl    4(%esp), %ecx
292         xorl    %eax, %eax
293         xorl    %edx, %edx
294         movl    (%ecx), %eax
295         movl    4(%ecx), %edx
296         ret
297         END(dtrace_fuword64_nocheck)
298
299 /*
300 void dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which, int fault, int fltoffs, uintptr_t illval)
301 */
302
303         ENTRY(dtrace_probe_error)
304         pushl   %ebp
305         movl    %esp, %ebp
306         pushl   0x1c(%ebp)
307         pushl   0x18(%ebp)
308         pushl   0x14(%ebp)
309         pushl   0x10(%ebp)
310         pushl   0xc(%ebp)
311         pushl   0x8(%ebp)
312         pushl   dtrace_probeid_error
313         call    dtrace_probe
314         movl    %ebp, %esp
315         popl    %ebp
316         ret
317         END(dtrace_probe_error)
318
319 /*
320 void dtrace_membar_producer(void)
321 */
322
323         ENTRY(dtrace_membar_producer)
324         rep;    ret     /* use 2 byte return instruction when branch target */
325                         /* AMD Software Optimization Guide - Section 6.2 */
326         END(dtrace_membar_producer)
327
328 /*
329 void dtrace_membar_consumer(void)
330 */
331
332         ENTRY(dtrace_membar_consumer)
333         rep;    ret     /* use 2 byte return instruction when branch target */
334                         /* AMD Software Optimization Guide - Section 6.2 */
335         END(dtrace_membar_consumer)
336
337 /*
338 dtrace_icookie_t dtrace_interrupt_disable(void)
339 */
340         ENTRY(dtrace_interrupt_disable)
341         pushfl
342         popl    %eax
343         cli
344         ret
345         END(dtrace_interrupt_disable)
346
347 /*
348 void dtrace_interrupt_enable(dtrace_icookie_t cookie)
349 */
350         ENTRY(dtrace_interrupt_enable)
351         movl    4(%esp), %eax
352         pushl   %eax
353         popfl
354         ret
355         END(dtrace_interrupt_enable)