blob: b2654bbfff471e130f1927f4e64b1bfcd7e09737 [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
395
396
397/* Signed 32-to-64 multiply. */
398.globl VG_(helper_imul_32_64)
399VG_(helper_imul_32_64):
400 pushl %eax
401 pushl %edx
402 movl 16(%esp), %eax
403 imull 12(%esp)
404 movl %eax, 16(%esp)
405 movl %edx, 12(%esp)
406 popl %edx
407 popl %eax
408 ret
409
410/* Signed 16-to-32 multiply. */
411.globl VG_(helper_imul_16_32)
412VG_(helper_imul_16_32):
413 pushl %eax
414 pushl %edx
415 movw 16(%esp), %ax
416 imulw 12(%esp)
417 movw %ax, 16(%esp)
418 movw %dx, 12(%esp)
419 popl %edx
420 popl %eax
421 ret
422
423/* Signed 8-to-16 multiply. */
424.globl VG_(helper_imul_8_16)
425VG_(helper_imul_8_16):
426 pushl %eax
427 pushl %edx
428 movb 16(%esp), %al
429 imulb 12(%esp)
430 movw %ax, 16(%esp)
431 popl %edx
432 popl %eax
433 ret
434
435
436
437
438
439
440/* Unsigned 32-to-64 multiply. */
441.globl VG_(helper_mul_32_64)
442VG_(helper_mul_32_64):
443 pushl %eax
444 pushl %edx
445 movl 16(%esp), %eax
446 mull 12(%esp)
447 movl %eax, 16(%esp)
448 movl %edx, 12(%esp)
449 popl %edx
450 popl %eax
451 ret
452
453/* Unsigned 16-to-32 multiply. */
454.globl VG_(helper_mul_16_32)
455VG_(helper_mul_16_32):
456 pushl %eax
457 pushl %edx
458 movw 16(%esp), %ax
459 mulw 12(%esp)
460 movw %ax, 16(%esp)
461 movw %dx, 12(%esp)
462 popl %edx
463 popl %eax
464 ret
465
466/* Unsigned 8-to-16 multiply. */
467.globl VG_(helper_mul_8_16)
468VG_(helper_mul_8_16):
469 pushl %eax
470 pushl %edx
471 movb 16(%esp), %al
472 mulb 12(%esp)
473 movw %ax, 16(%esp)
474 popl %edx
475 popl %eax
476 ret
477
478
479
480
481/* Unsigned 64-into-32 divide. */
482.globl VG_(helper_div_64_32)
483VG_(helper_div_64_32):
484 pushl %eax
485 pushl %edx
486 movl 16(%esp),%eax
487 movl 12(%esp),%edx
488 divl 20(%esp)
489 movl %eax,16(%esp)
490 movl %edx,12(%esp)
491 popl %edx
492 popl %eax
493 ret
494
495/* Signed 64-into-32 divide. */
496.globl VG_(helper_idiv_64_32)
497VG_(helper_idiv_64_32):
498 pushl %eax
499 pushl %edx
500 movl 16(%esp),%eax
501 movl 12(%esp),%edx
502 idivl 20(%esp)
503 movl %eax,16(%esp)
504 movl %edx,12(%esp)
505 popl %edx
506 popl %eax
507 ret
508
509/* Unsigned 32-into-16 divide. */
510.globl VG_(helper_div_32_16)
511VG_(helper_div_32_16):
512 pushl %eax
513 pushl %edx
514 movw 16(%esp),%ax
515 movw 12(%esp),%dx
516 divw 20(%esp)
517 movw %ax,16(%esp)
518 movw %dx,12(%esp)
519 popl %edx
520 popl %eax
521 ret
522
523/* Signed 32-into-16 divide. */
524.globl VG_(helper_idiv_32_16)
525VG_(helper_idiv_32_16):
526 pushl %eax
527 pushl %edx
528 movw 16(%esp),%ax
529 movw 12(%esp),%dx
530 idivw 20(%esp)
531 movw %ax,16(%esp)
532 movw %dx,12(%esp)
533 popl %edx
534 popl %eax
535 ret
536
537/* Unsigned 16-into-8 divide. */
538.globl VG_(helper_div_16_8)
539VG_(helper_div_16_8):
540 pushl %eax
541 movw 12(%esp),%ax
542 divb 16(%esp)
543 movb %ah,12(%esp)
544 movb %al,8(%esp)
545 popl %eax
546 ret
547
548/* Signed 16-into-8 divide. */
549.globl VG_(helper_idiv_16_8)
550VG_(helper_idiv_16_8):
551 pushl %eax
552 movw 12(%esp),%ax
553 idivb 16(%esp)
554 movb %ah,12(%esp)
555 movb %al,8(%esp)
556 popl %eax
557 ret
558
559
560##--------------------------------------------------------------------##
561##--- end vg_helpers.S ---##
562##--------------------------------------------------------------------##