blob: 62db9ec1d7d596fe05460b060f6fb2416a57bb43 [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
sewardj9316cba2002-05-03 20:52:53 +0000346 movl 12(%esp), %eax
sewardjde4a1d02002-03-22 01:27:54 +0000347 bsrl 8(%esp), %eax
sewardj9316cba2002-05-03 20:52:53 +0000348 movl %eax, 12(%esp)
sewardjde4a1d02002-03-22 01:27:54 +0000349 popl %eax
350 ret
351
352.global VG_(helper_bsf)
353VG_(helper_bsf):
354 pushl %eax
sewardj9316cba2002-05-03 20:52:53 +0000355 movl 12(%esp), %eax
sewardjde4a1d02002-03-22 01:27:54 +0000356 bsfl 8(%esp), %eax
sewardj9316cba2002-05-03 20:52:53 +0000357 movl %eax, 12(%esp)
sewardjde4a1d02002-03-22 01:27:54 +0000358 popl %eax
359 ret
360
361
sewardjde4a1d02002-03-22 01:27:54 +0000362/* 32-bit double-length shift left/right.
363 On entry:
364 amount
365 src
366 dst
367 RA <- %esp
368*/
369.global VG_(helper_shldl)
370VG_(helper_shldl):
371 pushl %eax
372 pushl %ebx
373 pushl %ecx
374
375 movb 24(%esp), %cl
376 movl 20(%esp), %ebx
377 movl 16(%esp), %eax
378 shldl %cl, %ebx, %eax
379 movl %eax, 16(%esp)
380
381 popl %ecx
382 popl %ebx
383 popl %eax
384 ret
385
386.global VG_(helper_shldw)
387VG_(helper_shldw):
388 pushl %eax
389 pushl %ebx
390 pushl %ecx
391
392 movb 24(%esp), %cl
393 movw 20(%esp), %bx
394 movw 16(%esp), %ax
395 shldw %cl, %bx, %ax
396 movw %ax, 16(%esp)
397
398 popl %ecx
399 popl %ebx
400 popl %eax
401 ret
402
403.global VG_(helper_shrdl)
404VG_(helper_shrdl):
405 pushl %eax
406 pushl %ebx
407 pushl %ecx
408
409 movb 24(%esp), %cl
410 movl 20(%esp), %ebx
411 movl 16(%esp), %eax
412 shrdl %cl, %ebx, %eax
413 movl %eax, 16(%esp)
414
415 popl %ecx
416 popl %ebx
417 popl %eax
418 ret
419
420.global VG_(helper_shrdw)
421VG_(helper_shrdw):
422 pushl %eax
423 pushl %ebx
424 pushl %ecx
425
426 movb 24(%esp), %cl
427 movw 20(%esp), %bx
428 movw 16(%esp), %ax
429 shrdw %cl, %bx, %ax
430 movw %ax, 16(%esp)
431
432 popl %ecx
433 popl %ebx
434 popl %eax
435 ret
436
437
438/* Get the direction flag, and return either 1 or -1. */
439.global VG_(helper_get_dirflag)
440VG_(helper_get_dirflag):
441 pushfl
442 pushl %eax
443
444 pushfl
445 popl %eax
446 shrl $10, %eax
447 andl $1, %eax
448 jnz L1
449 movl $1, %eax
450 jmp L2
451L1: movl $-1, %eax
452L2: movl %eax, 12(%esp)
453
454 popl %eax
455 popfl
456 ret
457
458
459/* Clear/set the direction flag. */
460.global VG_(helper_CLD)
461VG_(helper_CLD):
462 cld
463 ret
464
465.global VG_(helper_STD)
466VG_(helper_STD):
467 std
468 ret
469
470
471
472/* Signed 32-to-64 multiply. */
473.globl VG_(helper_imul_32_64)
474VG_(helper_imul_32_64):
475 pushl %eax
476 pushl %edx
477 movl 16(%esp), %eax
478 imull 12(%esp)
479 movl %eax, 16(%esp)
480 movl %edx, 12(%esp)
481 popl %edx
482 popl %eax
483 ret
484
485/* Signed 16-to-32 multiply. */
486.globl VG_(helper_imul_16_32)
487VG_(helper_imul_16_32):
488 pushl %eax
489 pushl %edx
490 movw 16(%esp), %ax
491 imulw 12(%esp)
492 movw %ax, 16(%esp)
493 movw %dx, 12(%esp)
494 popl %edx
495 popl %eax
496 ret
497
498/* Signed 8-to-16 multiply. */
499.globl VG_(helper_imul_8_16)
500VG_(helper_imul_8_16):
501 pushl %eax
502 pushl %edx
503 movb 16(%esp), %al
504 imulb 12(%esp)
505 movw %ax, 16(%esp)
506 popl %edx
507 popl %eax
508 ret
509
510
511
512
513
514
515/* Unsigned 32-to-64 multiply. */
516.globl VG_(helper_mul_32_64)
517VG_(helper_mul_32_64):
518 pushl %eax
519 pushl %edx
520 movl 16(%esp), %eax
521 mull 12(%esp)
522 movl %eax, 16(%esp)
523 movl %edx, 12(%esp)
524 popl %edx
525 popl %eax
526 ret
527
528/* Unsigned 16-to-32 multiply. */
529.globl VG_(helper_mul_16_32)
530VG_(helper_mul_16_32):
531 pushl %eax
532 pushl %edx
533 movw 16(%esp), %ax
534 mulw 12(%esp)
535 movw %ax, 16(%esp)
536 movw %dx, 12(%esp)
537 popl %edx
538 popl %eax
539 ret
540
541/* Unsigned 8-to-16 multiply. */
542.globl VG_(helper_mul_8_16)
543VG_(helper_mul_8_16):
544 pushl %eax
545 pushl %edx
546 movb 16(%esp), %al
547 mulb 12(%esp)
548 movw %ax, 16(%esp)
549 popl %edx
550 popl %eax
551 ret
552
553
554
555
556/* Unsigned 64-into-32 divide. */
557.globl VG_(helper_div_64_32)
558VG_(helper_div_64_32):
559 pushl %eax
560 pushl %edx
561 movl 16(%esp),%eax
562 movl 12(%esp),%edx
563 divl 20(%esp)
564 movl %eax,16(%esp)
565 movl %edx,12(%esp)
566 popl %edx
567 popl %eax
568 ret
569
570/* Signed 64-into-32 divide. */
571.globl VG_(helper_idiv_64_32)
572VG_(helper_idiv_64_32):
573 pushl %eax
574 pushl %edx
575 movl 16(%esp),%eax
576 movl 12(%esp),%edx
577 idivl 20(%esp)
578 movl %eax,16(%esp)
579 movl %edx,12(%esp)
580 popl %edx
581 popl %eax
582 ret
583
584/* Unsigned 32-into-16 divide. */
585.globl VG_(helper_div_32_16)
586VG_(helper_div_32_16):
587 pushl %eax
588 pushl %edx
589 movw 16(%esp),%ax
590 movw 12(%esp),%dx
591 divw 20(%esp)
592 movw %ax,16(%esp)
593 movw %dx,12(%esp)
594 popl %edx
595 popl %eax
596 ret
597
598/* Signed 32-into-16 divide. */
599.globl VG_(helper_idiv_32_16)
600VG_(helper_idiv_32_16):
601 pushl %eax
602 pushl %edx
603 movw 16(%esp),%ax
604 movw 12(%esp),%dx
605 idivw 20(%esp)
606 movw %ax,16(%esp)
607 movw %dx,12(%esp)
608 popl %edx
609 popl %eax
610 ret
611
612/* Unsigned 16-into-8 divide. */
613.globl VG_(helper_div_16_8)
614VG_(helper_div_16_8):
615 pushl %eax
616 movw 12(%esp),%ax
617 divb 16(%esp)
618 movb %ah,12(%esp)
619 movb %al,8(%esp)
620 popl %eax
621 ret
622
623/* Signed 16-into-8 divide. */
624.globl VG_(helper_idiv_16_8)
625VG_(helper_idiv_16_8):
626 pushl %eax
627 movw 12(%esp),%ax
628 idivb 16(%esp)
629 movb %ah,12(%esp)
630 movb %al,8(%esp)
631 popl %eax
632 ret
633
634
635##--------------------------------------------------------------------##
636##--- end vg_helpers.S ---##
637##--------------------------------------------------------------------##