blob: 2315da4221158317d9dc0ceb33d6fe71967d4807 [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
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
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
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):
336 pushfl
337 pushl %eax
338
339 pushfl
340 popl %eax
341 shrl $10, %eax
342 andl $1, %eax
343 jnz L1
344 movl $1, %eax
345 jmp L2
346L1: movl $-1, %eax
347L2: movl %eax, 12(%esp)
348
349 popl %eax
350 popfl
351 ret
352
353
354/* Clear/set the direction flag. */
355.global VG_(helper_CLD)
356VG_(helper_CLD):
357 cld
358 ret
359
360.global VG_(helper_STD)
361VG_(helper_STD):
362 std
363 ret
364
sewardj7d78e782002-06-02 00:04:00 +0000365/* Clear/set the carry flag. */
366.global VG_(helper_CLC)
367VG_(helper_CLC):
368 clc
369 ret
sewardjde4a1d02002-03-22 01:27:54 +0000370
sewardj7d78e782002-06-02 00:04:00 +0000371.global VG_(helper_STC)
372VG_(helper_STC):
373 stc
374 ret
sewardjde4a1d02002-03-22 01:27:54 +0000375
376/* Signed 32-to-64 multiply. */
377.globl VG_(helper_imul_32_64)
378VG_(helper_imul_32_64):
379 pushl %eax
380 pushl %edx
381 movl 16(%esp), %eax
382 imull 12(%esp)
383 movl %eax, 16(%esp)
384 movl %edx, 12(%esp)
385 popl %edx
386 popl %eax
387 ret
388
389/* Signed 16-to-32 multiply. */
390.globl VG_(helper_imul_16_32)
391VG_(helper_imul_16_32):
392 pushl %eax
393 pushl %edx
394 movw 16(%esp), %ax
395 imulw 12(%esp)
396 movw %ax, 16(%esp)
397 movw %dx, 12(%esp)
398 popl %edx
399 popl %eax
400 ret
401
402/* Signed 8-to-16 multiply. */
403.globl VG_(helper_imul_8_16)
404VG_(helper_imul_8_16):
405 pushl %eax
406 pushl %edx
407 movb 16(%esp), %al
408 imulb 12(%esp)
409 movw %ax, 16(%esp)
410 popl %edx
411 popl %eax
412 ret
413
414
415
416
417
418
419/* Unsigned 32-to-64 multiply. */
420.globl VG_(helper_mul_32_64)
421VG_(helper_mul_32_64):
422 pushl %eax
423 pushl %edx
424 movl 16(%esp), %eax
425 mull 12(%esp)
426 movl %eax, 16(%esp)
427 movl %edx, 12(%esp)
428 popl %edx
429 popl %eax
430 ret
431
432/* Unsigned 16-to-32 multiply. */
433.globl VG_(helper_mul_16_32)
434VG_(helper_mul_16_32):
435 pushl %eax
436 pushl %edx
437 movw 16(%esp), %ax
438 mulw 12(%esp)
439 movw %ax, 16(%esp)
440 movw %dx, 12(%esp)
441 popl %edx
442 popl %eax
443 ret
444
445/* Unsigned 8-to-16 multiply. */
446.globl VG_(helper_mul_8_16)
447VG_(helper_mul_8_16):
448 pushl %eax
449 pushl %edx
450 movb 16(%esp), %al
451 mulb 12(%esp)
452 movw %ax, 16(%esp)
453 popl %edx
454 popl %eax
455 ret
456
457
458
459
460/* Unsigned 64-into-32 divide. */
461.globl VG_(helper_div_64_32)
462VG_(helper_div_64_32):
463 pushl %eax
464 pushl %edx
465 movl 16(%esp),%eax
466 movl 12(%esp),%edx
467 divl 20(%esp)
468 movl %eax,16(%esp)
469 movl %edx,12(%esp)
470 popl %edx
471 popl %eax
472 ret
473
474/* Signed 64-into-32 divide. */
475.globl VG_(helper_idiv_64_32)
476VG_(helper_idiv_64_32):
477 pushl %eax
478 pushl %edx
479 movl 16(%esp),%eax
480 movl 12(%esp),%edx
481 idivl 20(%esp)
482 movl %eax,16(%esp)
483 movl %edx,12(%esp)
484 popl %edx
485 popl %eax
486 ret
487
488/* Unsigned 32-into-16 divide. */
489.globl VG_(helper_div_32_16)
490VG_(helper_div_32_16):
491 pushl %eax
492 pushl %edx
493 movw 16(%esp),%ax
494 movw 12(%esp),%dx
495 divw 20(%esp)
496 movw %ax,16(%esp)
497 movw %dx,12(%esp)
498 popl %edx
499 popl %eax
500 ret
501
502/* Signed 32-into-16 divide. */
503.globl VG_(helper_idiv_32_16)
504VG_(helper_idiv_32_16):
505 pushl %eax
506 pushl %edx
507 movw 16(%esp),%ax
508 movw 12(%esp),%dx
509 idivw 20(%esp)
510 movw %ax,16(%esp)
511 movw %dx,12(%esp)
512 popl %edx
513 popl %eax
514 ret
515
516/* Unsigned 16-into-8 divide. */
517.globl VG_(helper_div_16_8)
518VG_(helper_div_16_8):
519 pushl %eax
520 movw 12(%esp),%ax
521 divb 16(%esp)
522 movb %ah,12(%esp)
523 movb %al,8(%esp)
524 popl %eax
525 ret
526
527/* Signed 16-into-8 divide. */
528.globl VG_(helper_idiv_16_8)
529VG_(helper_idiv_16_8):
530 pushl %eax
531 movw 12(%esp),%ax
532 idivb 16(%esp)
533 movb %ah,12(%esp)
534 movb %al,8(%esp)
535 popl %eax
536 ret
537
538
539##--------------------------------------------------------------------##
540##--- end vg_helpers.S ---##
541##--------------------------------------------------------------------##