blob: b2af7d79a8bf60ff896fe1ee9ca230986f741fb8 [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/*
njnc9539842002-10-02 13:26:35 +00008 This file is part of Valgrind, an extensible x86 protected-mode
9 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +000010
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
njn25e49d8e72002-09-23 09:36:25 +000029 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000030*/
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
njne427a662002-10-02 11:08:25 +000061 call VG_(core_panic)
sewardj54cacf02002-04-12 23:24:59 +000062
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
sewardjde4a1d02002-03-22 01:27:54 +000089/* Fetch the time-stamp-ctr reg.
90 On entry:
91 dummy, replaced by %EAX value
92 dummy, replaced by %EDX value
93 RA <- %esp
94*/
95.global VG_(helper_RDTSC)
96VG_(helper_RDTSC):
97 pushl %eax
98 pushl %edx
99 rdtsc
100 movl %edx, 12(%esp)
101 movl %eax, 16(%esp)
102 popl %edx
103 popl %eax
104 ret
105
106
107/* Do the CPUID instruction.
108 On entry:
109 dummy, replaced by %EAX value
110 dummy, replaced by %EBX value
111 dummy, replaced by %ECX value
112 dummy, replaced by %EDX value
113 RA <- %esp
114
115 As emulating a real CPUID is kinda hard, as it
116 has to return different values depending on EAX,
117 we just pretend to not support CPUID at all until
118 it becomes a problem. This will for sure disable
119 all MMX / 3dnow checks so they don't bother us
120 with code we don't understand. (Dirk <dirk@kde.org>)
121
122 http://www.sandpile.org/ia32/cpuid.htm
123
124 (Later: we instead pretend to be like Werner's P54C P133, that is
125 an original pre-MMX Pentium).
126 <werner> cpuid words (0): 0x1 0x756e6547 0x6c65746e 0x49656e69
127 <werner> cpuid words (1): 0x52b 0x0 0x0 0x1bf
128*/
129.global VG_(helper_CPUID)
130VG_(helper_CPUID):
131 pushl %eax
132 pushl %ebx
133 pushl %ecx
134 pushl %edx
135 movl 32(%esp), %eax
136/*
137 cpuid
138*/
139/*
140 xor %eax,%eax
141 xor %ebx,%ebx
142 xor %ecx,%ecx
143 xor %edx,%edx
144*/
145 cmpl $0, %eax
146 jz cpuid__0
147 movl $0x52b, %eax
148 movl $0x0, %ebx
149 movl $0x0, %ecx
150 movl $0x1bf, %edx
151 jmp cpuid__99
152cpuid__0:
153 movl $0x1, %eax
154 movl $0x756e6547, %ebx
155 movl $0x6c65746e, %ecx
156 movl $0x49656e69, %edx
157cpuid__99:
158
159 movl %edx, 20(%esp)
160 movl %ecx, 24(%esp)
161 movl %ebx, 28(%esp)
162 movl %eax, 32(%esp)
163 popl %edx
164 popl %ecx
165 popl %ebx
166 popl %eax
167 ret
168
169
170/* Fetch the FPU status register.
171 On entry:
172 dummy, replaced by result
173 RA <- %esp
174*/
175.global VG_(helper_fstsw_AX)
176VG_(helper_fstsw_AX):
177 pushl %eax
178 pushl %esi
179 movl VGOFF_(m_fpustate), %esi
180 frstor (%ebp, %esi, 4)
181 fstsw %ax
182 popl %esi
183 movw %ax, 8(%esp)
184 popl %eax
185 ret
186
187
188/* Copy %ah into %eflags.
189 On entry:
190 value of %eax
191 RA <- %esp
192*/
193.global VG_(helper_SAHF)
194VG_(helper_SAHF):
195 pushl %eax
196 movl 8(%esp), %eax
197 sahf
198 popl %eax
199 ret
200
201
sewardj4d0ab1f2002-03-24 10:00:09 +0000202/* Do %al = DAS(%al). Note that the passed param has %AL as the least
203 significant 8 bits, since it was generated with GETB %AL,
204 some-temp. Fortunately %al is the least significant 8 bits of
205 %eax anyway, which is why it's safe to work with %eax as a
206 whole.
207
208 On entry:
209 value of %eax
210 RA <- %esp
211*/
212.global VG_(helper_DAS)
213VG_(helper_DAS):
214 pushl %eax
215 movl 8(%esp), %eax
216 das
217 movl %eax, 8(%esp)
218 popl %eax
219 ret
220
221
sewardjfe8a1662002-03-24 11:54:07 +0000222/* Similarly, do %al = DAA(%al). */
223.global VG_(helper_DAA)
224VG_(helper_DAA):
225 pushl %eax
226 movl 8(%esp), %eax
227 daa
228 movl %eax, 8(%esp)
229 popl %eax
230 ret
231
sewardj4d0ab1f2002-03-24 10:00:09 +0000232
sewardjde4a1d02002-03-22 01:27:54 +0000233/* Bit scan forwards/reverse. Sets flags (??).
234 On entry:
235 value, replaced by result
236 RA <- %esp
237*/
238.global VG_(helper_bsr)
239VG_(helper_bsr):
240 pushl %eax
sewardj9316cba2002-05-03 20:52:53 +0000241 movl 12(%esp), %eax
sewardjde4a1d02002-03-22 01:27:54 +0000242 bsrl 8(%esp), %eax
sewardj9316cba2002-05-03 20:52:53 +0000243 movl %eax, 12(%esp)
sewardjde4a1d02002-03-22 01:27:54 +0000244 popl %eax
245 ret
246
247.global VG_(helper_bsf)
248VG_(helper_bsf):
249 pushl %eax
sewardj9316cba2002-05-03 20:52:53 +0000250 movl 12(%esp), %eax
sewardjde4a1d02002-03-22 01:27:54 +0000251 bsfl 8(%esp), %eax
sewardj9316cba2002-05-03 20:52:53 +0000252 movl %eax, 12(%esp)
sewardjde4a1d02002-03-22 01:27:54 +0000253 popl %eax
254 ret
255
256
sewardjde4a1d02002-03-22 01:27:54 +0000257/* 32-bit double-length shift left/right.
258 On entry:
259 amount
260 src
261 dst
262 RA <- %esp
263*/
264.global VG_(helper_shldl)
265VG_(helper_shldl):
266 pushl %eax
267 pushl %ebx
268 pushl %ecx
269
270 movb 24(%esp), %cl
271 movl 20(%esp), %ebx
272 movl 16(%esp), %eax
273 shldl %cl, %ebx, %eax
274 movl %eax, 16(%esp)
275
276 popl %ecx
277 popl %ebx
278 popl %eax
279 ret
280
281.global VG_(helper_shldw)
282VG_(helper_shldw):
283 pushl %eax
284 pushl %ebx
285 pushl %ecx
286
287 movb 24(%esp), %cl
288 movw 20(%esp), %bx
289 movw 16(%esp), %ax
290 shldw %cl, %bx, %ax
291 movw %ax, 16(%esp)
292
293 popl %ecx
294 popl %ebx
295 popl %eax
296 ret
297
298.global VG_(helper_shrdl)
299VG_(helper_shrdl):
300 pushl %eax
301 pushl %ebx
302 pushl %ecx
303
304 movb 24(%esp), %cl
305 movl 20(%esp), %ebx
306 movl 16(%esp), %eax
307 shrdl %cl, %ebx, %eax
308 movl %eax, 16(%esp)
309
310 popl %ecx
311 popl %ebx
312 popl %eax
313 ret
314
315.global VG_(helper_shrdw)
316VG_(helper_shrdw):
317 pushl %eax
318 pushl %ebx
319 pushl %ecx
320
321 movb 24(%esp), %cl
322 movw 20(%esp), %bx
323 movw 16(%esp), %ax
324 shrdw %cl, %bx, %ax
325 movw %ax, 16(%esp)
326
327 popl %ecx
328 popl %ebx
329 popl %eax
330 ret
331
332
333/* Get the direction flag, and return either 1 or -1. */
334.global VG_(helper_get_dirflag)
335VG_(helper_get_dirflag):
sewardjde4a1d02002-03-22 01:27:54 +0000336 pushl %eax
337
sewardjfa492d42002-12-08 18:20:01 +0000338 movl VGOFF_(m_dflag), %eax
339 movl (%ebp, %eax, 4), %eax
340 movl %eax, 8(%esp)
341
sewardjde4a1d02002-03-22 01:27:54 +0000342 popl %eax
sewardjde4a1d02002-03-22 01:27:54 +0000343 ret
344
sewardjde4a1d02002-03-22 01:27:54 +0000345/* Clear/set the direction flag. */
346.global VG_(helper_CLD)
347VG_(helper_CLD):
sewardjfa492d42002-12-08 18:20:01 +0000348 pushl %eax
349
350 movl VGOFF_(m_dflag), %eax
351 movl $1, (%ebp, %eax, 4)
352
353 popl %eax
sewardjde4a1d02002-03-22 01:27:54 +0000354 ret
355
356.global VG_(helper_STD)
357VG_(helper_STD):
sewardjfa492d42002-12-08 18:20:01 +0000358 pushl %eax
359
360 movl VGOFF_(m_dflag), %eax
361 movl $-1, (%ebp, %eax, 4)
362
363 popl %eax
sewardjde4a1d02002-03-22 01:27:54 +0000364 ret
365
sewardj7d78e782002-06-02 00:04:00 +0000366/* Clear/set the carry flag. */
367.global VG_(helper_CLC)
368VG_(helper_CLC):
369 clc
370 ret
sewardjde4a1d02002-03-22 01:27:54 +0000371
sewardj7d78e782002-06-02 00:04:00 +0000372.global VG_(helper_STC)
373VG_(helper_STC):
374 stc
375 ret
sewardjde4a1d02002-03-22 01:27:54 +0000376
377/* Signed 32-to-64 multiply. */
378.globl VG_(helper_imul_32_64)
379VG_(helper_imul_32_64):
380 pushl %eax
381 pushl %edx
382 movl 16(%esp), %eax
383 imull 12(%esp)
384 movl %eax, 16(%esp)
385 movl %edx, 12(%esp)
386 popl %edx
387 popl %eax
388 ret
389
390/* Signed 16-to-32 multiply. */
391.globl VG_(helper_imul_16_32)
392VG_(helper_imul_16_32):
393 pushl %eax
394 pushl %edx
395 movw 16(%esp), %ax
396 imulw 12(%esp)
397 movw %ax, 16(%esp)
398 movw %dx, 12(%esp)
399 popl %edx
400 popl %eax
401 ret
402
403/* Signed 8-to-16 multiply. */
404.globl VG_(helper_imul_8_16)
405VG_(helper_imul_8_16):
406 pushl %eax
407 pushl %edx
408 movb 16(%esp), %al
409 imulb 12(%esp)
410 movw %ax, 16(%esp)
411 popl %edx
412 popl %eax
413 ret
414
415
416
417
418
419
420/* Unsigned 32-to-64 multiply. */
421.globl VG_(helper_mul_32_64)
422VG_(helper_mul_32_64):
423 pushl %eax
424 pushl %edx
425 movl 16(%esp), %eax
426 mull 12(%esp)
427 movl %eax, 16(%esp)
428 movl %edx, 12(%esp)
429 popl %edx
430 popl %eax
431 ret
432
433/* Unsigned 16-to-32 multiply. */
434.globl VG_(helper_mul_16_32)
435VG_(helper_mul_16_32):
436 pushl %eax
437 pushl %edx
438 movw 16(%esp), %ax
439 mulw 12(%esp)
440 movw %ax, 16(%esp)
441 movw %dx, 12(%esp)
442 popl %edx
443 popl %eax
444 ret
445
446/* Unsigned 8-to-16 multiply. */
447.globl VG_(helper_mul_8_16)
448VG_(helper_mul_8_16):
449 pushl %eax
450 pushl %edx
451 movb 16(%esp), %al
452 mulb 12(%esp)
453 movw %ax, 16(%esp)
454 popl %edx
455 popl %eax
456 ret
457
458
459
460
461/* Unsigned 64-into-32 divide. */
462.globl VG_(helper_div_64_32)
463VG_(helper_div_64_32):
464 pushl %eax
465 pushl %edx
466 movl 16(%esp),%eax
467 movl 12(%esp),%edx
468 divl 20(%esp)
469 movl %eax,16(%esp)
470 movl %edx,12(%esp)
471 popl %edx
472 popl %eax
473 ret
474
475/* Signed 64-into-32 divide. */
476.globl VG_(helper_idiv_64_32)
477VG_(helper_idiv_64_32):
478 pushl %eax
479 pushl %edx
480 movl 16(%esp),%eax
481 movl 12(%esp),%edx
482 idivl 20(%esp)
483 movl %eax,16(%esp)
484 movl %edx,12(%esp)
485 popl %edx
486 popl %eax
487 ret
488
489/* Unsigned 32-into-16 divide. */
490.globl VG_(helper_div_32_16)
491VG_(helper_div_32_16):
492 pushl %eax
493 pushl %edx
494 movw 16(%esp),%ax
495 movw 12(%esp),%dx
496 divw 20(%esp)
497 movw %ax,16(%esp)
498 movw %dx,12(%esp)
499 popl %edx
500 popl %eax
501 ret
502
503/* Signed 32-into-16 divide. */
504.globl VG_(helper_idiv_32_16)
505VG_(helper_idiv_32_16):
506 pushl %eax
507 pushl %edx
508 movw 16(%esp),%ax
509 movw 12(%esp),%dx
510 idivw 20(%esp)
511 movw %ax,16(%esp)
512 movw %dx,12(%esp)
513 popl %edx
514 popl %eax
515 ret
516
517/* Unsigned 16-into-8 divide. */
518.globl VG_(helper_div_16_8)
519VG_(helper_div_16_8):
520 pushl %eax
521 movw 12(%esp),%ax
522 divb 16(%esp)
523 movb %ah,12(%esp)
524 movb %al,8(%esp)
525 popl %eax
526 ret
527
528/* Signed 16-into-8 divide. */
529.globl VG_(helper_idiv_16_8)
530VG_(helper_idiv_16_8):
531 pushl %eax
532 movw 12(%esp),%ax
533 idivb 16(%esp)
534 movb %ah,12(%esp)
535 movb %al,8(%esp)
536 popl %eax
537 ret
538
sewardj51096432002-12-14 23:59:09 +0000539
540/* Undefined instruction (generates SIGILL) */
541.globl VG_(helper_undefined_instruction)
542VG_(helper_undefined_instruction):
5431: ud2
544 jmp 1b
545
sewardjde4a1d02002-03-22 01:27:54 +0000546##--------------------------------------------------------------------##
547##--- end vg_helpers.S ---##
548##--------------------------------------------------------------------##