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