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