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