blob: 29689225d332cdcd4db0e241e909e899f02ec2cf [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/* Fetch the time-stamp-ctr reg.
150 On entry:
151 dummy, replaced by %EAX value
152 dummy, replaced by %EDX value
153 RA <- %esp
154*/
155.global VG_(helper_RDTSC)
156VG_(helper_RDTSC):
157 pushl %eax
158 pushl %edx
159 rdtsc
160 movl %edx, 12(%esp)
161 movl %eax, 16(%esp)
162 popl %edx
163 popl %eax
164 ret
165
166
167/* Do the CPUID instruction.
168 On entry:
169 dummy, replaced by %EAX value
170 dummy, replaced by %EBX value
171 dummy, replaced by %ECX value
172 dummy, replaced by %EDX value
173 RA <- %esp
174
175 As emulating a real CPUID is kinda hard, as it
176 has to return different values depending on EAX,
177 we just pretend to not support CPUID at all until
178 it becomes a problem. This will for sure disable
179 all MMX / 3dnow checks so they don't bother us
180 with code we don't understand. (Dirk <dirk@kde.org>)
181
182 http://www.sandpile.org/ia32/cpuid.htm
183
184 (Later: we instead pretend to be like Werner's P54C P133, that is
185 an original pre-MMX Pentium).
186 <werner> cpuid words (0): 0x1 0x756e6547 0x6c65746e 0x49656e69
187 <werner> cpuid words (1): 0x52b 0x0 0x0 0x1bf
188*/
189.global VG_(helper_CPUID)
190VG_(helper_CPUID):
191 pushl %eax
192 pushl %ebx
193 pushl %ecx
194 pushl %edx
195 movl 32(%esp), %eax
196/*
197 cpuid
198*/
199/*
200 xor %eax,%eax
201 xor %ebx,%ebx
202 xor %ecx,%ecx
203 xor %edx,%edx
204*/
205 cmpl $0, %eax
206 jz cpuid__0
207 movl $0x52b, %eax
208 movl $0x0, %ebx
209 movl $0x0, %ecx
210 movl $0x1bf, %edx
211 jmp cpuid__99
212cpuid__0:
213 movl $0x1, %eax
214 movl $0x756e6547, %ebx
215 movl $0x6c65746e, %ecx
216 movl $0x49656e69, %edx
217cpuid__99:
218
219 movl %edx, 20(%esp)
220 movl %ecx, 24(%esp)
221 movl %ebx, 28(%esp)
222 movl %eax, 32(%esp)
223 popl %edx
224 popl %ecx
225 popl %ebx
226 popl %eax
227 ret
228
229
230/* Fetch the FPU status register.
231 On entry:
232 dummy, replaced by result
233 RA <- %esp
234*/
235.global VG_(helper_fstsw_AX)
236VG_(helper_fstsw_AX):
237 pushl %eax
238 pushl %esi
239 movl VGOFF_(m_fpustate), %esi
240 frstor (%ebp, %esi, 4)
241 fstsw %ax
242 popl %esi
243 movw %ax, 8(%esp)
244 popl %eax
245 ret
246
247
248/* Copy %ah into %eflags.
249 On entry:
250 value of %eax
251 RA <- %esp
252*/
253.global VG_(helper_SAHF)
254VG_(helper_SAHF):
255 pushl %eax
256 movl 8(%esp), %eax
257 sahf
258 popl %eax
259 ret
260
261
sewardj4d0ab1f2002-03-24 10:00:09 +0000262/* Do %al = DAS(%al). Note that the passed param has %AL as the least
263 significant 8 bits, since it was generated with GETB %AL,
264 some-temp. Fortunately %al is the least significant 8 bits of
265 %eax anyway, which is why it's safe to work with %eax as a
266 whole.
267
268 On entry:
269 value of %eax
270 RA <- %esp
271*/
272.global VG_(helper_DAS)
273VG_(helper_DAS):
274 pushl %eax
275 movl 8(%esp), %eax
276 das
277 movl %eax, 8(%esp)
278 popl %eax
279 ret
280
281
sewardjfe8a1662002-03-24 11:54:07 +0000282/* Similarly, do %al = DAA(%al). */
283.global VG_(helper_DAA)
284VG_(helper_DAA):
285 pushl %eax
286 movl 8(%esp), %eax
287 daa
288 movl %eax, 8(%esp)
289 popl %eax
290 ret
291
sewardj4d0ab1f2002-03-24 10:00:09 +0000292
sewardjde4a1d02002-03-22 01:27:54 +0000293/* Bit scan forwards/reverse. Sets flags (??).
294 On entry:
295 value, replaced by result
296 RA <- %esp
297*/
298.global VG_(helper_bsr)
299VG_(helper_bsr):
300 pushl %eax
sewardj9316cba2002-05-03 20:52:53 +0000301 movl 12(%esp), %eax
sewardjde4a1d02002-03-22 01:27:54 +0000302 bsrl 8(%esp), %eax
sewardj9316cba2002-05-03 20:52:53 +0000303 movl %eax, 12(%esp)
sewardjde4a1d02002-03-22 01:27:54 +0000304 popl %eax
305 ret
306
307.global VG_(helper_bsf)
308VG_(helper_bsf):
309 pushl %eax
sewardj9316cba2002-05-03 20:52:53 +0000310 movl 12(%esp), %eax
sewardjde4a1d02002-03-22 01:27:54 +0000311 bsfl 8(%esp), %eax
sewardj9316cba2002-05-03 20:52:53 +0000312 movl %eax, 12(%esp)
sewardjde4a1d02002-03-22 01:27:54 +0000313 popl %eax
314 ret
315
316
sewardjde4a1d02002-03-22 01:27:54 +0000317/* 32-bit double-length shift left/right.
318 On entry:
319 amount
320 src
321 dst
322 RA <- %esp
323*/
324.global VG_(helper_shldl)
325VG_(helper_shldl):
326 pushl %eax
327 pushl %ebx
328 pushl %ecx
329
330 movb 24(%esp), %cl
331 movl 20(%esp), %ebx
332 movl 16(%esp), %eax
333 shldl %cl, %ebx, %eax
334 movl %eax, 16(%esp)
335
336 popl %ecx
337 popl %ebx
338 popl %eax
339 ret
340
341.global VG_(helper_shldw)
342VG_(helper_shldw):
343 pushl %eax
344 pushl %ebx
345 pushl %ecx
346
347 movb 24(%esp), %cl
348 movw 20(%esp), %bx
349 movw 16(%esp), %ax
350 shldw %cl, %bx, %ax
351 movw %ax, 16(%esp)
352
353 popl %ecx
354 popl %ebx
355 popl %eax
356 ret
357
358.global VG_(helper_shrdl)
359VG_(helper_shrdl):
360 pushl %eax
361 pushl %ebx
362 pushl %ecx
363
364 movb 24(%esp), %cl
365 movl 20(%esp), %ebx
366 movl 16(%esp), %eax
367 shrdl %cl, %ebx, %eax
368 movl %eax, 16(%esp)
369
370 popl %ecx
371 popl %ebx
372 popl %eax
373 ret
374
375.global VG_(helper_shrdw)
376VG_(helper_shrdw):
377 pushl %eax
378 pushl %ebx
379 pushl %ecx
380
381 movb 24(%esp), %cl
382 movw 20(%esp), %bx
383 movw 16(%esp), %ax
384 shrdw %cl, %bx, %ax
385 movw %ax, 16(%esp)
386
387 popl %ecx
388 popl %ebx
389 popl %eax
390 ret
391
392
393/* Get the direction flag, and return either 1 or -1. */
394.global VG_(helper_get_dirflag)
395VG_(helper_get_dirflag):
396 pushfl
397 pushl %eax
398
399 pushfl
400 popl %eax
401 shrl $10, %eax
402 andl $1, %eax
403 jnz L1
404 movl $1, %eax
405 jmp L2
406L1: movl $-1, %eax
407L2: movl %eax, 12(%esp)
408
409 popl %eax
410 popfl
411 ret
412
413
414/* Clear/set the direction flag. */
415.global VG_(helper_CLD)
416VG_(helper_CLD):
417 cld
418 ret
419
420.global VG_(helper_STD)
421VG_(helper_STD):
422 std
423 ret
424
425
426
427/* Signed 32-to-64 multiply. */
428.globl VG_(helper_imul_32_64)
429VG_(helper_imul_32_64):
430 pushl %eax
431 pushl %edx
432 movl 16(%esp), %eax
433 imull 12(%esp)
434 movl %eax, 16(%esp)
435 movl %edx, 12(%esp)
436 popl %edx
437 popl %eax
438 ret
439
440/* Signed 16-to-32 multiply. */
441.globl VG_(helper_imul_16_32)
442VG_(helper_imul_16_32):
443 pushl %eax
444 pushl %edx
445 movw 16(%esp), %ax
446 imulw 12(%esp)
447 movw %ax, 16(%esp)
448 movw %dx, 12(%esp)
449 popl %edx
450 popl %eax
451 ret
452
453/* Signed 8-to-16 multiply. */
454.globl VG_(helper_imul_8_16)
455VG_(helper_imul_8_16):
456 pushl %eax
457 pushl %edx
458 movb 16(%esp), %al
459 imulb 12(%esp)
460 movw %ax, 16(%esp)
461 popl %edx
462 popl %eax
463 ret
464
465
466
467
468
469
470/* Unsigned 32-to-64 multiply. */
471.globl VG_(helper_mul_32_64)
472VG_(helper_mul_32_64):
473 pushl %eax
474 pushl %edx
475 movl 16(%esp), %eax
476 mull 12(%esp)
477 movl %eax, 16(%esp)
478 movl %edx, 12(%esp)
479 popl %edx
480 popl %eax
481 ret
482
483/* Unsigned 16-to-32 multiply. */
484.globl VG_(helper_mul_16_32)
485VG_(helper_mul_16_32):
486 pushl %eax
487 pushl %edx
488 movw 16(%esp), %ax
489 mulw 12(%esp)
490 movw %ax, 16(%esp)
491 movw %dx, 12(%esp)
492 popl %edx
493 popl %eax
494 ret
495
496/* Unsigned 8-to-16 multiply. */
497.globl VG_(helper_mul_8_16)
498VG_(helper_mul_8_16):
499 pushl %eax
500 pushl %edx
501 movb 16(%esp), %al
502 mulb 12(%esp)
503 movw %ax, 16(%esp)
504 popl %edx
505 popl %eax
506 ret
507
508
509
510
511/* Unsigned 64-into-32 divide. */
512.globl VG_(helper_div_64_32)
513VG_(helper_div_64_32):
514 pushl %eax
515 pushl %edx
516 movl 16(%esp),%eax
517 movl 12(%esp),%edx
518 divl 20(%esp)
519 movl %eax,16(%esp)
520 movl %edx,12(%esp)
521 popl %edx
522 popl %eax
523 ret
524
525/* Signed 64-into-32 divide. */
526.globl VG_(helper_idiv_64_32)
527VG_(helper_idiv_64_32):
528 pushl %eax
529 pushl %edx
530 movl 16(%esp),%eax
531 movl 12(%esp),%edx
532 idivl 20(%esp)
533 movl %eax,16(%esp)
534 movl %edx,12(%esp)
535 popl %edx
536 popl %eax
537 ret
538
539/* Unsigned 32-into-16 divide. */
540.globl VG_(helper_div_32_16)
541VG_(helper_div_32_16):
542 pushl %eax
543 pushl %edx
544 movw 16(%esp),%ax
545 movw 12(%esp),%dx
546 divw 20(%esp)
547 movw %ax,16(%esp)
548 movw %dx,12(%esp)
549 popl %edx
550 popl %eax
551 ret
552
553/* Signed 32-into-16 divide. */
554.globl VG_(helper_idiv_32_16)
555VG_(helper_idiv_32_16):
556 pushl %eax
557 pushl %edx
558 movw 16(%esp),%ax
559 movw 12(%esp),%dx
560 idivw 20(%esp)
561 movw %ax,16(%esp)
562 movw %dx,12(%esp)
563 popl %edx
564 popl %eax
565 ret
566
567/* Unsigned 16-into-8 divide. */
568.globl VG_(helper_div_16_8)
569VG_(helper_div_16_8):
570 pushl %eax
571 movw 12(%esp),%ax
572 divb 16(%esp)
573 movb %ah,12(%esp)
574 movb %al,8(%esp)
575 popl %eax
576 ret
577
578/* Signed 16-into-8 divide. */
579.globl VG_(helper_idiv_16_8)
580VG_(helper_idiv_16_8):
581 pushl %eax
582 movw 12(%esp),%ax
583 idivb 16(%esp)
584 movb %ah,12(%esp)
585 movb %al,8(%esp)
586 popl %eax
587 ret
588
589
590##--------------------------------------------------------------------##
591##--- end vg_helpers.S ---##
592##--------------------------------------------------------------------##