blob: e80208115424844e66e2cf9800758e14342e72fa [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2##--------------------------------------------------------------------##
3##--- Support routines for the JITter output. ---##
4##--- vg_helpers.S ---##
5##--------------------------------------------------------------------##
6
7/*
8 This file is part of Valgrind, an x86 protected-mode emulator
9 designed for debugging and profiling binaries on x86-Unixes.
10
11 Copyright (C) 2000-2002 Julian Seward
12 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000013
14 This program is free software; you can redistribute it and/or
15 modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation; either version 2 of the
17 License, or (at your option) any later version.
18
19 This program is distributed in the hope that it will be useful, but
20 WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General Public License for more details.
23
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, write to the Free Software
26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
27 02111-1307, USA.
28
29 The GNU General Public License is contained in the file LICENSE.
30*/
31
32#include "vg_constants.h"
33
sewardj54cacf02002-04-12 23:24:59 +000034/* ------------------ SIMULATED CPU HELPERS ------------------ */
35/* A couple of stubs for returns which we want to catch: signal
36 returns and pthread returns. In the latter case, the thread's
37 return value is in %EAX, so we pass this as the first argument
38 to the request. In both cases we use the user request mechanism.
39 You need to to read the definition of VALGRIND_MAGIC_SEQUENCE
40 in valgrind.h to make sense of this.
41*/
42.global VG_(signalreturn_bogusRA)
43VG_(signalreturn_bogusRA):
44 subl $20, %esp # allocate arg block
45 movl %esp, %edx # %edx == &_zzq_args[0]
46 movl $VG_USERREQ__SIGNAL_RETURNS, 0(%edx) # request
47 movl $0, 4(%edx) # arg1
48 movl $0, 8(%edx) # arg2
49 movl $0, 12(%edx) # arg3
50 movl $0, 16(%edx) # arg4
51 movl %edx, %eax
52 # and now the magic sequence itself:
53 roll $29, %eax
54 roll $3, %eax
55 rorl $27, %eax
56 rorl $5, %eax
57 roll $13, %eax
58 roll $19, %eax
59 # should never get here
60 pushl $signalreturn_bogusRA_panic_msg
61 call VG_(panic)
62
63.data
64signalreturn_bogusRA_panic_msg:
65.ascii "vg_signalreturn_bogusRA: VG_USERREQ__SIGNAL_RETURNS was missed"
66.byte 0
67.text
68
sewardjde4a1d02002-03-22 01:27:54 +000069
sewardjbc5b99f2002-04-13 00:08:51 +000070
71.global VG_(pthreadreturn_bogusRA)
72VG_(pthreadreturn_bogusRA):
73 subl $20, %esp # allocate arg block
74 movl %esp, %edx # %edx == &_zzq_args[0]
75 movl $VG_USERREQ__PTHREAD_RETURNS, 0(%edx) # request
76 movl %eax, 4(%edx) # arg1 == thread return value
77 movl $0, 8(%edx) # arg2
78 movl $0, 12(%edx) # arg3
79 movl $0, 16(%edx) # arg4
80 movl %edx, %eax
81 # and now the magic sequence itself:
82 roll $29, %eax
83 roll $3, %eax
84 rorl $27, %eax
85 rorl $5, %eax
86 roll $13, %eax
87 roll $19, %eax
88 # should never get here
89 pushl $pthreadreturn_bogusRA_panic_msg
90 call VG_(panic)
91
92.data
93pthreadreturn_bogusRA_panic_msg:
94.ascii "vg_pthreadreturn_bogusRA: VG_USERREQ__PTHREAD_RETURNS was missed"
95.byte 0
96.text
97
98
99
100
sewardj54cacf02002-04-12 23:24:59 +0000101
102/* ------------------ REAL CPU HELPERS ------------------ */
103/* The rest of this lot run on the real CPU. */
104
sewardjde4a1d02002-03-22 01:27:54 +0000105/* Various helper routines, for instructions which are just too
106 darn tedious for the JITter to output code in-line:
107
108 * integer division
109 * integer multiplication
110 * setting and getting obscure eflags
111 * double-length shifts
112
113 All routines use a standard calling convention designed for
114 calling from translations, in which the incoming args are
115 underneath the return address, the callee saves _all_ registers,
116 and the incoming parameters can be modified, to return results.
117*/
118
119
sewardjde4a1d02002-03-22 01:27:54 +0000120.global VG_(helper_value_check0_fail)
121VG_(helper_value_check0_fail):
122 pushal
123 call VG_(helperc_value_check0_fail)
124 popal
125 ret
126
127.global VG_(helper_value_check1_fail)
128VG_(helper_value_check1_fail):
129 pushal
130 call VG_(helperc_value_check1_fail)
131 popal
132 ret
133
134.global VG_(helper_value_check2_fail)
135VG_(helper_value_check2_fail):
136 pushal
137 call VG_(helperc_value_check2_fail)
138 popal
139 ret
140
141.global VG_(helper_value_check4_fail)
142VG_(helper_value_check4_fail):
143 pushal
144 call VG_(helperc_value_check4_fail)
145 popal
146 ret
147
148
sewardjde4a1d02002-03-22 01:27:54 +0000149/* Do a original-code-write check for the address in %ebp. */
150.global VG_(helper_smc_check4)
151VG_(helper_smc_check4):
152#if VG_SMC_FASTCHECK_IN_C
153
154 # save the live regs
155 pushl %eax
156 pushl %ebx
157 pushl %ecx
158 pushl %edx
159 pushl %esi
160 pushl %edi
161
162 pushl %ebp
163 call VG_(smc_check4)
164 addl $4, %esp
165
166 popl %edi
167 popl %esi
168 popl %edx
169 popl %ecx
170 popl %ebx
171 popl %eax
172
173 ret
174#else
175 incl VG_(smc_total_check4s)
176 pushl %ebp
177 shrl $VG_SMC_CACHE_SHIFT, %ebp
178 andl $VG_SMC_CACHE_MASK, %ebp
179 cmpb $0, VG_(smc_cache)(%ebp)
180 jnz vg_smc_cache_failure
181 addl $4, %esp
182 ret
183 vg_smc_cache_failure:
184 popl %ebp
185 pushal
186 pushl %ebp
187 call VG_(smc_check4)
188 addl $4, %esp
189 popal
190 ret
191#endif
192
193
194/* Fetch the time-stamp-ctr reg.
195 On entry:
196 dummy, replaced by %EAX value
197 dummy, replaced by %EDX value
198 RA <- %esp
199*/
200.global VG_(helper_RDTSC)
201VG_(helper_RDTSC):
202 pushl %eax
203 pushl %edx
204 rdtsc
205 movl %edx, 12(%esp)
206 movl %eax, 16(%esp)
207 popl %edx
208 popl %eax
209 ret
210
211
212/* Do the CPUID instruction.
213 On entry:
214 dummy, replaced by %EAX value
215 dummy, replaced by %EBX value
216 dummy, replaced by %ECX value
217 dummy, replaced by %EDX value
218 RA <- %esp
219
220 As emulating a real CPUID is kinda hard, as it
221 has to return different values depending on EAX,
222 we just pretend to not support CPUID at all until
223 it becomes a problem. This will for sure disable
224 all MMX / 3dnow checks so they don't bother us
225 with code we don't understand. (Dirk <dirk@kde.org>)
226
227 http://www.sandpile.org/ia32/cpuid.htm
228
229 (Later: we instead pretend to be like Werner's P54C P133, that is
230 an original pre-MMX Pentium).
231 <werner> cpuid words (0): 0x1 0x756e6547 0x6c65746e 0x49656e69
232 <werner> cpuid words (1): 0x52b 0x0 0x0 0x1bf
233*/
234.global VG_(helper_CPUID)
235VG_(helper_CPUID):
236 pushl %eax
237 pushl %ebx
238 pushl %ecx
239 pushl %edx
240 movl 32(%esp), %eax
241/*
242 cpuid
243*/
244/*
245 xor %eax,%eax
246 xor %ebx,%ebx
247 xor %ecx,%ecx
248 xor %edx,%edx
249*/
250 cmpl $0, %eax
251 jz cpuid__0
252 movl $0x52b, %eax
253 movl $0x0, %ebx
254 movl $0x0, %ecx
255 movl $0x1bf, %edx
256 jmp cpuid__99
257cpuid__0:
258 movl $0x1, %eax
259 movl $0x756e6547, %ebx
260 movl $0x6c65746e, %ecx
261 movl $0x49656e69, %edx
262cpuid__99:
263
264 movl %edx, 20(%esp)
265 movl %ecx, 24(%esp)
266 movl %ebx, 28(%esp)
267 movl %eax, 32(%esp)
268 popl %edx
269 popl %ecx
270 popl %ebx
271 popl %eax
272 ret
273
274
275/* Fetch the FPU status register.
276 On entry:
277 dummy, replaced by result
278 RA <- %esp
279*/
280.global VG_(helper_fstsw_AX)
281VG_(helper_fstsw_AX):
282 pushl %eax
283 pushl %esi
284 movl VGOFF_(m_fpustate), %esi
285 frstor (%ebp, %esi, 4)
286 fstsw %ax
287 popl %esi
288 movw %ax, 8(%esp)
289 popl %eax
290 ret
291
292
293/* Copy %ah into %eflags.
294 On entry:
295 value of %eax
296 RA <- %esp
297*/
298.global VG_(helper_SAHF)
299VG_(helper_SAHF):
300 pushl %eax
301 movl 8(%esp), %eax
302 sahf
303 popl %eax
304 ret
305
306
sewardj4d0ab1f2002-03-24 10:00:09 +0000307/* Do %al = DAS(%al). Note that the passed param has %AL as the least
308 significant 8 bits, since it was generated with GETB %AL,
309 some-temp. Fortunately %al is the least significant 8 bits of
310 %eax anyway, which is why it's safe to work with %eax as a
311 whole.
312
313 On entry:
314 value of %eax
315 RA <- %esp
316*/
317.global VG_(helper_DAS)
318VG_(helper_DAS):
319 pushl %eax
320 movl 8(%esp), %eax
321 das
322 movl %eax, 8(%esp)
323 popl %eax
324 ret
325
326
sewardjfe8a1662002-03-24 11:54:07 +0000327/* Similarly, do %al = DAA(%al). */
328.global VG_(helper_DAA)
329VG_(helper_DAA):
330 pushl %eax
331 movl 8(%esp), %eax
332 daa
333 movl %eax, 8(%esp)
334 popl %eax
335 ret
336
sewardj4d0ab1f2002-03-24 10:00:09 +0000337
sewardjde4a1d02002-03-22 01:27:54 +0000338/* Bit scan forwards/reverse. Sets flags (??).
339 On entry:
340 value, replaced by result
341 RA <- %esp
342*/
343.global VG_(helper_bsr)
344VG_(helper_bsr):
345 pushl %eax
346 bsrl 8(%esp), %eax
347 movl %eax, 8(%esp)
348 popl %eax
349 ret
350
351.global VG_(helper_bsf)
352VG_(helper_bsf):
353 pushl %eax
354 bsfl 8(%esp), %eax
355 movl %eax, 8(%esp)
356 popl %eax
357 ret
358
359
sewardjde4a1d02002-03-22 01:27:54 +0000360/* 32-bit double-length shift left/right.
361 On entry:
362 amount
363 src
364 dst
365 RA <- %esp
366*/
367.global VG_(helper_shldl)
368VG_(helper_shldl):
369 pushl %eax
370 pushl %ebx
371 pushl %ecx
372
373 movb 24(%esp), %cl
374 movl 20(%esp), %ebx
375 movl 16(%esp), %eax
376 shldl %cl, %ebx, %eax
377 movl %eax, 16(%esp)
378
379 popl %ecx
380 popl %ebx
381 popl %eax
382 ret
383
384.global VG_(helper_shldw)
385VG_(helper_shldw):
386 pushl %eax
387 pushl %ebx
388 pushl %ecx
389
390 movb 24(%esp), %cl
391 movw 20(%esp), %bx
392 movw 16(%esp), %ax
393 shldw %cl, %bx, %ax
394 movw %ax, 16(%esp)
395
396 popl %ecx
397 popl %ebx
398 popl %eax
399 ret
400
401.global VG_(helper_shrdl)
402VG_(helper_shrdl):
403 pushl %eax
404 pushl %ebx
405 pushl %ecx
406
407 movb 24(%esp), %cl
408 movl 20(%esp), %ebx
409 movl 16(%esp), %eax
410 shrdl %cl, %ebx, %eax
411 movl %eax, 16(%esp)
412
413 popl %ecx
414 popl %ebx
415 popl %eax
416 ret
417
418.global VG_(helper_shrdw)
419VG_(helper_shrdw):
420 pushl %eax
421 pushl %ebx
422 pushl %ecx
423
424 movb 24(%esp), %cl
425 movw 20(%esp), %bx
426 movw 16(%esp), %ax
427 shrdw %cl, %bx, %ax
428 movw %ax, 16(%esp)
429
430 popl %ecx
431 popl %ebx
432 popl %eax
433 ret
434
435
436/* Get the direction flag, and return either 1 or -1. */
437.global VG_(helper_get_dirflag)
438VG_(helper_get_dirflag):
439 pushfl
440 pushl %eax
441
442 pushfl
443 popl %eax
444 shrl $10, %eax
445 andl $1, %eax
446 jnz L1
447 movl $1, %eax
448 jmp L2
449L1: movl $-1, %eax
450L2: movl %eax, 12(%esp)
451
452 popl %eax
453 popfl
454 ret
455
456
457/* Clear/set the direction flag. */
458.global VG_(helper_CLD)
459VG_(helper_CLD):
460 cld
461 ret
462
463.global VG_(helper_STD)
464VG_(helper_STD):
465 std
466 ret
467
468
469
470/* Signed 32-to-64 multiply. */
471.globl VG_(helper_imul_32_64)
472VG_(helper_imul_32_64):
473 pushl %eax
474 pushl %edx
475 movl 16(%esp), %eax
476 imull 12(%esp)
477 movl %eax, 16(%esp)
478 movl %edx, 12(%esp)
479 popl %edx
480 popl %eax
481 ret
482
483/* Signed 16-to-32 multiply. */
484.globl VG_(helper_imul_16_32)
485VG_(helper_imul_16_32):
486 pushl %eax
487 pushl %edx
488 movw 16(%esp), %ax
489 imulw 12(%esp)
490 movw %ax, 16(%esp)
491 movw %dx, 12(%esp)
492 popl %edx
493 popl %eax
494 ret
495
496/* Signed 8-to-16 multiply. */
497.globl VG_(helper_imul_8_16)
498VG_(helper_imul_8_16):
499 pushl %eax
500 pushl %edx
501 movb 16(%esp), %al
502 imulb 12(%esp)
503 movw %ax, 16(%esp)
504 popl %edx
505 popl %eax
506 ret
507
508
509
510
511
512
513/* Unsigned 32-to-64 multiply. */
514.globl VG_(helper_mul_32_64)
515VG_(helper_mul_32_64):
516 pushl %eax
517 pushl %edx
518 movl 16(%esp), %eax
519 mull 12(%esp)
520 movl %eax, 16(%esp)
521 movl %edx, 12(%esp)
522 popl %edx
523 popl %eax
524 ret
525
526/* Unsigned 16-to-32 multiply. */
527.globl VG_(helper_mul_16_32)
528VG_(helper_mul_16_32):
529 pushl %eax
530 pushl %edx
531 movw 16(%esp), %ax
532 mulw 12(%esp)
533 movw %ax, 16(%esp)
534 movw %dx, 12(%esp)
535 popl %edx
536 popl %eax
537 ret
538
539/* Unsigned 8-to-16 multiply. */
540.globl VG_(helper_mul_8_16)
541VG_(helper_mul_8_16):
542 pushl %eax
543 pushl %edx
544 movb 16(%esp), %al
545 mulb 12(%esp)
546 movw %ax, 16(%esp)
547 popl %edx
548 popl %eax
549 ret
550
551
552
553
554/* Unsigned 64-into-32 divide. */
555.globl VG_(helper_div_64_32)
556VG_(helper_div_64_32):
557 pushl %eax
558 pushl %edx
559 movl 16(%esp),%eax
560 movl 12(%esp),%edx
561 divl 20(%esp)
562 movl %eax,16(%esp)
563 movl %edx,12(%esp)
564 popl %edx
565 popl %eax
566 ret
567
568/* Signed 64-into-32 divide. */
569.globl VG_(helper_idiv_64_32)
570VG_(helper_idiv_64_32):
571 pushl %eax
572 pushl %edx
573 movl 16(%esp),%eax
574 movl 12(%esp),%edx
575 idivl 20(%esp)
576 movl %eax,16(%esp)
577 movl %edx,12(%esp)
578 popl %edx
579 popl %eax
580 ret
581
582/* Unsigned 32-into-16 divide. */
583.globl VG_(helper_div_32_16)
584VG_(helper_div_32_16):
585 pushl %eax
586 pushl %edx
587 movw 16(%esp),%ax
588 movw 12(%esp),%dx
589 divw 20(%esp)
590 movw %ax,16(%esp)
591 movw %dx,12(%esp)
592 popl %edx
593 popl %eax
594 ret
595
596/* Signed 32-into-16 divide. */
597.globl VG_(helper_idiv_32_16)
598VG_(helper_idiv_32_16):
599 pushl %eax
600 pushl %edx
601 movw 16(%esp),%ax
602 movw 12(%esp),%dx
603 idivw 20(%esp)
604 movw %ax,16(%esp)
605 movw %dx,12(%esp)
606 popl %edx
607 popl %eax
608 ret
609
610/* Unsigned 16-into-8 divide. */
611.globl VG_(helper_div_16_8)
612VG_(helper_div_16_8):
613 pushl %eax
614 movw 12(%esp),%ax
615 divb 16(%esp)
616 movb %ah,12(%esp)
617 movb %al,8(%esp)
618 popl %eax
619 ret
620
621/* Signed 16-into-8 divide. */
622.globl VG_(helper_idiv_16_8)
623VG_(helper_idiv_16_8):
624 pushl %eax
625 movw 12(%esp),%ax
626 idivb 16(%esp)
627 movb %ah,12(%esp)
628 movb %al,8(%esp)
629 popl %eax
630 ret
631
632
633##--------------------------------------------------------------------##
634##--- end vg_helpers.S ---##
635##--------------------------------------------------------------------##