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