blob: 781175d49b6aaaceb7d65e8bdfeaa8930209d5a1 [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
292/* Bit scan forwards/reverse. Sets flags (??).
293 On entry:
294 value, replaced by result
295 RA <- %esp
296*/
297.global VG_(helper_bsr)
298VG_(helper_bsr):
299 pushl %eax
300 bsrl 8(%esp), %eax
301 movl %eax, 8(%esp)
302 popl %eax
303 ret
304
305.global VG_(helper_bsf)
306VG_(helper_bsf):
307 pushl %eax
308 bsfl 8(%esp), %eax
309 movl %eax, 8(%esp)
310 popl %eax
311 ret
312
313
314/* Bit test and set/reset/complement. Sets flags.
315 On entry:
316 src
317 dst
318 RA <- %esp
319*/
320.global VG_(helper_bt)
321VG_(helper_bt):
322 pushl %eax
323 movl 12(%esp), %eax
324 btl %eax, 8(%esp)
325 popl %eax
326 ret
327.global VG_(helper_bts)
328VG_(helper_bts):
329 pushl %eax
330 movl 12(%esp), %eax
331 btsl %eax, 8(%esp)
332 popl %eax
333 ret
334.global VG_(helper_btr)
335VG_(helper_btr):
336 pushl %eax
337 movl 12(%esp), %eax
338 btrl %eax, 8(%esp)
339 popl %eax
340 ret
341.global VG_(helper_btc)
342VG_(helper_btc):
343 pushl %eax
344 movl 12(%esp), %eax
345 btcl %eax, 8(%esp)
346 popl %eax
347 ret
348
349
350/* 32-bit double-length shift left/right.
351 On entry:
352 amount
353 src
354 dst
355 RA <- %esp
356*/
357.global VG_(helper_shldl)
358VG_(helper_shldl):
359 pushl %eax
360 pushl %ebx
361 pushl %ecx
362
363 movb 24(%esp), %cl
364 movl 20(%esp), %ebx
365 movl 16(%esp), %eax
366 shldl %cl, %ebx, %eax
367 movl %eax, 16(%esp)
368
369 popl %ecx
370 popl %ebx
371 popl %eax
372 ret
373
374.global VG_(helper_shldw)
375VG_(helper_shldw):
376 pushl %eax
377 pushl %ebx
378 pushl %ecx
379
380 movb 24(%esp), %cl
381 movw 20(%esp), %bx
382 movw 16(%esp), %ax
383 shldw %cl, %bx, %ax
384 movw %ax, 16(%esp)
385
386 popl %ecx
387 popl %ebx
388 popl %eax
389 ret
390
391.global VG_(helper_shrdl)
392VG_(helper_shrdl):
393 pushl %eax
394 pushl %ebx
395 pushl %ecx
396
397 movb 24(%esp), %cl
398 movl 20(%esp), %ebx
399 movl 16(%esp), %eax
400 shrdl %cl, %ebx, %eax
401 movl %eax, 16(%esp)
402
403 popl %ecx
404 popl %ebx
405 popl %eax
406 ret
407
408.global VG_(helper_shrdw)
409VG_(helper_shrdw):
410 pushl %eax
411 pushl %ebx
412 pushl %ecx
413
414 movb 24(%esp), %cl
415 movw 20(%esp), %bx
416 movw 16(%esp), %ax
417 shrdw %cl, %bx, %ax
418 movw %ax, 16(%esp)
419
420 popl %ecx
421 popl %ebx
422 popl %eax
423 ret
424
425
426/* Get the direction flag, and return either 1 or -1. */
427.global VG_(helper_get_dirflag)
428VG_(helper_get_dirflag):
429 pushfl
430 pushl %eax
431
432 pushfl
433 popl %eax
434 shrl $10, %eax
435 andl $1, %eax
436 jnz L1
437 movl $1, %eax
438 jmp L2
439L1: movl $-1, %eax
440L2: movl %eax, 12(%esp)
441
442 popl %eax
443 popfl
444 ret
445
446
447/* Clear/set the direction flag. */
448.global VG_(helper_CLD)
449VG_(helper_CLD):
450 cld
451 ret
452
453.global VG_(helper_STD)
454VG_(helper_STD):
455 std
456 ret
457
458
459
460/* Signed 32-to-64 multiply. */
461.globl VG_(helper_imul_32_64)
462VG_(helper_imul_32_64):
463 pushl %eax
464 pushl %edx
465 movl 16(%esp), %eax
466 imull 12(%esp)
467 movl %eax, 16(%esp)
468 movl %edx, 12(%esp)
469 popl %edx
470 popl %eax
471 ret
472
473/* Signed 16-to-32 multiply. */
474.globl VG_(helper_imul_16_32)
475VG_(helper_imul_16_32):
476 pushl %eax
477 pushl %edx
478 movw 16(%esp), %ax
479 imulw 12(%esp)
480 movw %ax, 16(%esp)
481 movw %dx, 12(%esp)
482 popl %edx
483 popl %eax
484 ret
485
486/* Signed 8-to-16 multiply. */
487.globl VG_(helper_imul_8_16)
488VG_(helper_imul_8_16):
489 pushl %eax
490 pushl %edx
491 movb 16(%esp), %al
492 imulb 12(%esp)
493 movw %ax, 16(%esp)
494 popl %edx
495 popl %eax
496 ret
497
498
499
500
501
502
503/* Unsigned 32-to-64 multiply. */
504.globl VG_(helper_mul_32_64)
505VG_(helper_mul_32_64):
506 pushl %eax
507 pushl %edx
508 movl 16(%esp), %eax
509 mull 12(%esp)
510 movl %eax, 16(%esp)
511 movl %edx, 12(%esp)
512 popl %edx
513 popl %eax
514 ret
515
516/* Unsigned 16-to-32 multiply. */
517.globl VG_(helper_mul_16_32)
518VG_(helper_mul_16_32):
519 pushl %eax
520 pushl %edx
521 movw 16(%esp), %ax
522 mulw 12(%esp)
523 movw %ax, 16(%esp)
524 movw %dx, 12(%esp)
525 popl %edx
526 popl %eax
527 ret
528
529/* Unsigned 8-to-16 multiply. */
530.globl VG_(helper_mul_8_16)
531VG_(helper_mul_8_16):
532 pushl %eax
533 pushl %edx
534 movb 16(%esp), %al
535 mulb 12(%esp)
536 movw %ax, 16(%esp)
537 popl %edx
538 popl %eax
539 ret
540
541
542
543
544/* Unsigned 64-into-32 divide. */
545.globl VG_(helper_div_64_32)
546VG_(helper_div_64_32):
547 pushl %eax
548 pushl %edx
549 movl 16(%esp),%eax
550 movl 12(%esp),%edx
551 divl 20(%esp)
552 movl %eax,16(%esp)
553 movl %edx,12(%esp)
554 popl %edx
555 popl %eax
556 ret
557
558/* Signed 64-into-32 divide. */
559.globl VG_(helper_idiv_64_32)
560VG_(helper_idiv_64_32):
561 pushl %eax
562 pushl %edx
563 movl 16(%esp),%eax
564 movl 12(%esp),%edx
565 idivl 20(%esp)
566 movl %eax,16(%esp)
567 movl %edx,12(%esp)
568 popl %edx
569 popl %eax
570 ret
571
572/* Unsigned 32-into-16 divide. */
573.globl VG_(helper_div_32_16)
574VG_(helper_div_32_16):
575 pushl %eax
576 pushl %edx
577 movw 16(%esp),%ax
578 movw 12(%esp),%dx
579 divw 20(%esp)
580 movw %ax,16(%esp)
581 movw %dx,12(%esp)
582 popl %edx
583 popl %eax
584 ret
585
586/* Signed 32-into-16 divide. */
587.globl VG_(helper_idiv_32_16)
588VG_(helper_idiv_32_16):
589 pushl %eax
590 pushl %edx
591 movw 16(%esp),%ax
592 movw 12(%esp),%dx
593 idivw 20(%esp)
594 movw %ax,16(%esp)
595 movw %dx,12(%esp)
596 popl %edx
597 popl %eax
598 ret
599
600/* Unsigned 16-into-8 divide. */
601.globl VG_(helper_div_16_8)
602VG_(helper_div_16_8):
603 pushl %eax
604 movw 12(%esp),%ax
605 divb 16(%esp)
606 movb %ah,12(%esp)
607 movb %al,8(%esp)
608 popl %eax
609 ret
610
611/* Signed 16-into-8 divide. */
612.globl VG_(helper_idiv_16_8)
613VG_(helper_idiv_16_8):
614 pushl %eax
615 movw 12(%esp),%ax
616 idivb 16(%esp)
617 movb %ah,12(%esp)
618 movb %al,8(%esp)
619 popl %eax
620 ret
621
622
623##--------------------------------------------------------------------##
624##--- end vg_helpers.S ---##
625##--------------------------------------------------------------------##