drd/tests/swapcontext: Add a swapcontext() test
[valgrind.git] / coregrind / m_trampoline.S
blobc2d642992ad26ad627cb985108b00fce41675dfc
2 /*--------------------------------------------------------------------*/
3 /*--- Trampoline code page stuff.                   m_trampoline.S ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
10   Copyright (C) 2000-2017 Julian Seward 
11      jseward@acm.org
12   Copyright (C) 2006-2017 OpenWorks LLP
13      info@open-works.co.uk
14         
15   This program is free software; you can redistribute it and/or
16   modify it under the terms of the GNU General Public License as
17   published by the Free Software Foundation; either version 2 of the
18   License, or (at your option) any later version.
20   This program is distributed in the hope that it will be useful, but
21   WITHOUT ANY WARRANTY; without even the implied warranty of
22   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23   General Public License for more details.
25   You should have received a copy of the GNU General Public License
26   along with this program; if not, see <http://www.gnu.org/licenses/>.
28   The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics_asm.h"
32 #include "pub_core_vkiscnums_asm.h"
34 /* ------------------ SIMULATED CPU HELPERS ------------------ */
35 /* 
36    Replacements for some functions to do with vsyscalls and signals.
37    This code runs on the simulated CPU.
39         
40 /*---------------------- x86-linux ----------------------*/
41 #if defined(VGP_x86_linux)
43 #       define UD2_16     ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
44 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
45 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
46 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
47 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
49         /* a leading page of unexecutable code */
50         UD2_PAGE
52 .global VG_(trampoline_stuff_start)
53 VG_(trampoline_stuff_start):
55 .global VG_(x86_linux_SUBST_FOR_sigreturn)
56 VG_(x86_linux_SUBST_FOR_sigreturn):
57         /* This is a very specific sequence which GDB uses to
58            recognize signal handler frames.  Also gcc: see
59            x86_fallback_frame_state() in
60            gcc-4.1.0/gcc/config/i386/linux-unwind.h */
61         popl    %eax
62         movl    $ __NR_sigreturn, %eax
63         int     $0x80
64         ud2
66 .global VG_(x86_linux_SUBST_FOR_rt_sigreturn)
67 VG_(x86_linux_SUBST_FOR_rt_sigreturn):
68         /* Likewise for rt signal frames */
69         movl    $ __NR_rt_sigreturn, %eax
70         int     $0x80
71         ud2
73 /* There's no particular reason that this needs to be handwritten
74    assembly, but since that's what this file contains, here's a
75    simple index implementation (written in C and compiled by gcc.)
77    unsigned char* REDIR_FOR_index ( const char* s, int c ) 
78    { 
79       unsigned char  ch = (unsigned char)((unsigned int)c); 
80       unsigned char* p  = (unsigned char*)s; 
81       while (1) { 
82          if (*p == ch) return p;
83          if (*p == 0)  return 0; 
84          p++; 
85       } 
86    }
88 .global VG_(x86_linux_REDIR_FOR_index)
89 .type   VG_(x86_linux_REDIR_FOR_index), @function
90 VG_(x86_linux_REDIR_FOR_index):
91         pushl   %ebp
92         movl    %esp, %ebp
93         movl    8(%ebp), %eax
94         movzbl  12(%ebp), %ecx
95         movzbl  (%eax), %edx
96         cmpb    %dl, %cl
97         jne     .L9
98         jmp     .L2
99 .L11:
100         addl    $1, %eax
101         movzbl  (%eax), %edx
102         cmpb    %dl, %cl
103         je      .L2
104 .L9:
105         testb   %dl, %dl
106         jne     .L11
107         xorl    %eax, %eax
108 .L2:
109         popl    %ebp
110         ret
111 .size VG_(x86_linux_REDIR_FOR_index), .-VG_(x86_linux_REDIR_FOR_index)
113 /* There's no particular reason that this needs to be handwritten
114    assembly, but since that's what this file contains, here's a
115    simple strlen implementation (written in C and compiled by gcc.)
117 .global VG_(x86_linux_REDIR_FOR_strlen)
118 .type   VG_(x86_linux_REDIR_FOR_strlen), @function
119 VG_(x86_linux_REDIR_FOR_strlen):
120         pushl   %ebp
121         movl    %esp, %ebp
122         movl    8(%ebp), %edx
123         movl    %edx, %eax
124         jmp     2f
125 1:      incl    %eax
126 2:      cmpb    $0, (%eax)
127         jne     1b
128         subl    %edx, %eax
129         popl    %ebp
130         ret
131 .size VG_(x86_linux_REDIR_FOR_strlen), .-VG_(x86_linux_REDIR_FOR_strlen)
134 .global VG_(trampoline_stuff_end)
135 VG_(trampoline_stuff_end):
137         /* and a trailing page of unexecutable code */
138         UD2_PAGE
140 #       undef UD2_16
141 #       undef UD2_64
142 #       undef UD2_256
143 #       undef UD2_1024
144 #       undef UD2_PAGE
145         
146 /*---------------------- amd64-linux ----------------------*/
147 #else
148 #if defined(VGP_amd64_linux)
150 #       define UD2_16     ud2 ; ud2 ; ud2 ; ud2 ;ud2 ; ud2 ; ud2 ; ud2
151 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
152 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
153 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
154 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
156         /* a leading page of unexecutable code */
157         UD2_PAGE
159 .global VG_(trampoline_stuff_start)
160 VG_(trampoline_stuff_start):
162 .global VG_(amd64_linux_SUBST_FOR_rt_sigreturn)
163 VG_(amd64_linux_SUBST_FOR_rt_sigreturn):
164         /* This is a very specific sequence which GDB uses to
165            recognize signal handler frames. */
166         movq    $__NR_rt_sigreturn, %rax
167         syscall
168         ud2
170 .global VG_(amd64_linux_REDIR_FOR_vgettimeofday)
171 .type   VG_(amd64_linux_REDIR_FOR_vgettimeofday), @function
172 VG_(amd64_linux_REDIR_FOR_vgettimeofday):
173 .LfnB2:
174         movq    $__NR_gettimeofday, %rax
175         syscall
176         ret
177 .LfnE2:
178 .size VG_(amd64_linux_REDIR_FOR_vgettimeofday), .-.LfnB2
179         
180 .global VG_(amd64_linux_REDIR_FOR_vtime)
181 .type   VG_(amd64_linux_REDIR_FOR_vtime), @function
182 VG_(amd64_linux_REDIR_FOR_vtime):
183 .LfnB3: 
184         movq    $__NR_time, %rax
185         syscall
186         ret
187 .LfnE3:
188 .size VG_(amd64_linux_REDIR_FOR_vtime), .-.LfnB3
190 .global VG_(amd64_linux_REDIR_FOR_vgetcpu)
191 .type   VG_(amd64_linux_REDIR_FOR_vgetcpu), @function
192 VG_(amd64_linux_REDIR_FOR_vgetcpu):
193 .LfnB4:
194         movq    $__NR_getcpu, %rax
195         syscall
196         ret
197 .LfnE4:
198 .size VG_(amd64_linux_REDIR_FOR_vgetcpu), .-.LfnB4
200 /* There's no particular reason that this needs to be handwritten
201    assembly, but since that's what this file contains, here's a
202    simple strlen implementation (written in C and compiled by gcc.)
204 .global VG_(amd64_linux_REDIR_FOR_strlen)
205 .type   VG_(amd64_linux_REDIR_FOR_strlen), @function
206 VG_(amd64_linux_REDIR_FOR_strlen):
207 .LfnB5:
208         xorl    %eax, %eax
209         cmpb    $0, (%rdi)
210         movq    %rdi, %rdx
211         je      .L41
212 .L40:   addq    $1, %rdx
213         cmpb    $0, (%rdx)
214         jne     .L40
215         movq    %rdx, %rax
216         subq    %rdi, %rax
217 .L41:   ret
218 .LfnE5:
219 .size VG_(amd64_linux_REDIR_FOR_strlen), .-VG_(amd64_linux_REDIR_FOR_strlen)
221 .global VG_(amd64_linux_REDIR_FOR_index)
222 .type   VG_(amd64_linux_REDIR_FOR_index), @function
223 VG_(amd64_linux_REDIR_FOR_index):
224         movzbl  (%rdi), %eax
225         movl    %esi, %edx
226         cmpb    %sil, %al
227         jne     .L4
228         jmp     .L5
229 .L10:
230         addq    $1, %rdi
231         movzbl  (%rdi), %eax
232         cmpb    %dl, %al
233         je      .L5
234 .L4:
235         testb   %al, %al
236         jne     .L10
237         xorl    %eax, %eax
238         ret
239 .L5:
240         movq    %rdi, %rax
241         ret
242 .size VG_(amd64_linux_REDIR_FOR_index), .-VG_(amd64_linux_REDIR_FOR_index)
246 /* A CIE for the above four functions, followed by their FDEs */
247         .section .eh_frame,"a",@progbits
248 .Lframe1:
249         .long   .LEcie1-.LScie1
250 .LScie1:
251         .long   0x0
252         .byte   0x1
253         .string "zR"
254         .uleb128 0x1
255         .sleb128 -8
256         .byte   0x10
257         .uleb128 0x1
258         .byte   0x3
259         .byte   0xc
260         .uleb128 0x7
261         .uleb128 0x8
262         .byte   0x90
263         .uleb128 0x1
264         .align 8
265 .LEcie1:
266 .LSfde2:
267         .long   .LEfde2-.LASfde2
268 .LASfde2:
269         .long   .LASfde2-.Lframe1
270         .long   .LfnB2
271         .long   .LfnE2-.LfnB2
272         .uleb128 0x0
273         .align 8
274 .LEfde2:
275 .LSfde3:
276         .long   .LEfde3-.LASfde3
277 .LASfde3:
278         .long   .LASfde3-.Lframe1
279         .long   .LfnB3
280         .long   .LfnE3-.LfnB3
281         .uleb128 0x0
282         .align 8
283 .LEfde3:
284 .LSfde4:
285         .long   .LEfde4-.LASfde4
286 .LASfde4:
287         .long   .LASfde4-.Lframe1
288         .long   .LfnB4
289         .long   .LfnE4-.LfnB4
290         .uleb128 0x0
291         .align 8
292 .LEfde4:
293 .LSfde5:
294         .long   .LEfde5-.LASfde5
295 .LASfde5:
296         .long   .LASfde5-.Lframe1
297         .long   .LfnB5
298         .long   .LfnE5-.LfnB5
299         .uleb128 0x0
300         .align 8
301 .LEfde5:
302         .previous
304 .global VG_(trampoline_stuff_end)
305 VG_(trampoline_stuff_end):
307         /* and a trailing page of unexecutable code */
308         UD2_PAGE
310 #       undef UD2_16
311 #       undef UD2_64
312 #       undef UD2_256
313 #       undef UD2_1024
314 #       undef UD2_PAGE
316 /*---------------- ppc32-linux ----------------*/
317 #else
318 #if defined(VGP_ppc32_linux)
320 #       define UD2_16     trap ; trap ; trap; trap
321 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
322 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
323 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
324 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
326         /* a leading page of unexecutable code */
327         UD2_PAGE
329 .global VG_(trampoline_stuff_start)
330 VG_(trampoline_stuff_start):
332 .global VG_(ppc32_linux_SUBST_FOR_sigreturn)
333 VG_(ppc32_linux_SUBST_FOR_sigreturn):
334         li 0,__NR_sigreturn
335         sc
336         .long 0 /*illegal insn*/
338 .global VG_(ppc32_linux_SUBST_FOR_rt_sigreturn)
339 VG_(ppc32_linux_SUBST_FOR_rt_sigreturn):
340         li 0,__NR_rt_sigreturn
341         sc
342         .long 0 /*illegal insn*/
343         
344 /* There's no particular reason that this needs to be handwritten
345    assembly, but since that's what this file contains, here's a
346    simple strlen implementation (written in C and compiled by gcc.)
348 .global VG_(ppc32_linux_REDIR_FOR_strlen)
349 .type   VG_(ppc32_linux_REDIR_FOR_strlen), @function
350 VG_(ppc32_linux_REDIR_FOR_strlen):
351         lbz 4,0(3)
352         li 9,0
353         cmpwi 0,4,0
354         beq- 0,.L18
355 .L19:
356         lbzu 5,1(3)
357         addi 9,9,1
358         cmpwi 0,5,0
359         bne+ 0,.L19
360 .L18:
361         mr 3,9
362         blr
363 .size VG_(ppc32_linux_REDIR_FOR_strlen), .-VG_(ppc32_linux_REDIR_FOR_strlen)
365 /* Ditto strcmp */
366 .global VG_(ppc32_linux_REDIR_FOR_strcmp)
367 .type   VG_(ppc32_linux_REDIR_FOR_strcmp), @function
368 VG_(ppc32_linux_REDIR_FOR_strcmp):
369 .L20:
370         lbz 0,0(3)
371         cmpwi 7,0,0
372         bne- 7,.L21
373         lbz 0,0(4)
374         li 11,0
375         cmpwi 7,0,0
376         beq- 7,.L22
377 .L21:
378         lbz 0,0(3)
379         li 11,-1
380         cmpwi 7,0,0
381         beq- 7,.L22
382         lbz 0,0(4)
383         li 11,1
384         cmpwi 7,0,0
385         beq- 7,.L22
386         lbz 9,0(3)
387         lbz 0,0(4)
388         li 11,-1
389         cmplw 7,9,0
390         blt- 7,.L22
391         lbz 9,0(3)
392         lbz 0,0(4)
393         li 11,1
394         addi 3,3,1
395         addi 4,4,1
396         cmplw 7,9,0
397         ble+ 7,.L20
398 .L22:
399         mr 3,11
400         blr
401 .size VG_(ppc32_linux_REDIR_FOR_strcmp), .-VG_(ppc32_linux_REDIR_FOR_strcmp)
403 /* Ditto index/strchr */
404 .global VG_(ppc32_linux_REDIR_FOR_strchr)
405 .type   VG_(ppc32_linux_REDIR_FOR_strchr), @function
406 VG_(ppc32_linux_REDIR_FOR_strchr):
407         lbz 0,0(3)
408         rlwinm 4,4,0,0xff
409         cmpw 7,4,0
410         beqlr 7
411         cmpwi 7,0,0
412         bne 7,.L308
413         b .L304
414 .L309:  
415         beq 6,.L304
416 .L308:  
417         lbzu 0,1(3)
418         cmpw 7,4,0
419         cmpwi 6,0,0
420         bne 7,.L309
421         blr
422 .L304:  
423         li 3,0
424         blr
425 .size   VG_(ppc32_linux_REDIR_FOR_strchr),.-VG_(ppc32_linux_REDIR_FOR_strchr)
426         
427 .global VG_(trampoline_stuff_end)
428 VG_(trampoline_stuff_end):
430         /* and a trailing page of unexecutable code */
431         UD2_PAGE
433 #       undef UD2_16
434 #       undef UD2_64
435 #       undef UD2_256
436 #       undef UD2_1024
437 #       undef UD2_PAGE
439 /*---------------- ppc64-linux ----------------*/
440 #else
441 #if defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
443 #       define UD2_16     trap ; trap ; trap; trap
444 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
445 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
446 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
447 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
449         /* a leading page of unexecutable code */
450         UD2_PAGE
452 .global VG_(trampoline_stuff_start)
453 VG_(trampoline_stuff_start):
455 .global VG_(ppc64_linux_SUBST_FOR_rt_sigreturn)
456 VG_(ppc64_linux_SUBST_FOR_rt_sigreturn):
457         li 0,__NR_rt_sigreturn
458         sc
459         .long 0 /*illegal insn*/
461         /* See comment in pub_core_trampoline.h for what this is for */
462 .global VG_(ppctoc_magic_redirect_return_stub)
463 VG_(ppctoc_magic_redirect_return_stub):
464         trap
466         /* this function is written using the "dotless" ABI convention */
467         .align 2
468         .globl VG_(ppc64_linux_REDIR_FOR_strlen)
469 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
470         /* Little Endian uses ELF version 2 */
471         .type VG_(ppc64_linux_REDIR_FOR_strlen),@function
472 VG_(ppc64_linux_REDIR_FOR_strlen):
473 #else
474         /* Big Endian uses ELF version 1 */
475         .section        ".opd","aw"
476         .align 3
477 VG_(ppc64_linux_REDIR_FOR_strlen):
478         .quad   .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0
479         .previous
480         .size   VG_(ppc64_linux_REDIR_FOR_strlen), \
481                         .L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
482         .type   VG_(ppc64_linux_REDIR_FOR_strlen), @function
484 .L.VG_(ppc64_linux_REDIR_FOR_strlen):
485 #endif
486 #if _CALL_ELF == 2
487 0:      addis        2,12,.TOC.-0b@ha
488         addi         2,2,.TOC.-0b@l
489         .localentry  VG_(ppc64_linux_REDIR_FOR_strlen), .-VG_(ppc64_linux_REDIR_FOR_strlen)
490 #endif
491         mr 9,3
492         lbz 0,0(3)
493         li 3,0
494         cmpwi 7,0,0
495         beqlr 7
496         li 3,0
497 .L01:
498         addi 0,3,1
499         extsw 3,0
500         lbzx 0,9,3
501         cmpwi 7,0,0
502         bne 7,.L01
503         blr
505 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
506         .size VG_(ppc64_linux_REDIR_FOR_strlen),.-VG_(ppc64_linux_REDIR_FOR_strlen)
507 #else
508         .size VG_(ppc64_linux_REDIR_FOR_strlen),.-.L.VG_(ppc64_linux_REDIR_FOR_strlen)
509 #endif
510         .long 0
511         .byte 0,0,0,0,0,0,0,0
512 .L0end:
514         /* this function is written using the "dotless" ABI convention */
515         .align 2
516         .globl VG_(ppc64_linux_REDIR_FOR_strchr)
517 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
518         .type   VG_(ppc64_linux_REDIR_FOR_strchr),@function
519 VG_(ppc64_linux_REDIR_FOR_strchr):
520 #else
521         .section        ".opd","aw"
522         .align 3
523 VG_(ppc64_linux_REDIR_FOR_strchr):
524         .quad   .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0
525         .previous
526         .size   VG_(ppc64_linux_REDIR_FOR_strchr), \
527                         .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
528         .type   VG_(ppc64_linux_REDIR_FOR_strchr),@function
530 .L.VG_(ppc64_linux_REDIR_FOR_strchr):
531 #endif
532 #if  _CALL_ELF == 2
533 0:      addis         2,12,.TOC.-0b@ha
534         addi         2,2,.TOC.-0b@l
535         .localentry VG_(ppc64_linux_REDIR_FOR_strchr), .-VG_(ppc64_linux_REDIR_FOR_strchr)
536 #endif
537         lbz 0,0(3)
538         rldicl 4,4,0,56
539         cmpw 7,4,0
540         beqlr 7
541         cmpdi 7,0,0
542         bne 7,.L18
543         b .L14
544 #if !defined VGP_ppc64be_linux || _CALL_ELF == 2
545         .size VG_(ppc64_linux_REDIR_FOR_strchr),.-VG_(ppc64_linux_REDIR_FOR_strchr)
546 #else
547         .size VG_(ppc64_linux_REDIR_FOR_strchr),.-.L.VG_(ppc64_linux_REDIR_FOR_strchr)
548 #endif
549 .L19:   
550         beq 6,.L14
551 .L18:   
552         lbzu 0,1(3)
553         cmpw 7,4,0
554         cmpdi 6,0,0
555         bne 7,.L19
556         blr
557 .L14:   
558         li 3,0
559         blr
560         .long 0
561         .byte 0,0,0,0,0,0,0,0
562 .L1end:
564         
565 .global VG_(trampoline_stuff_end)
566 VG_(trampoline_stuff_end):
568         /* and a trailing page of unexecutable code */
569         UD2_PAGE
571 #       undef UD2_16
572 #       undef UD2_64
573 #       undef UD2_256
574 #       undef UD2_1024
575 #       undef UD2_PAGE
577 /*---------------- arm-linux ----------------*/
578 #else
579 #if defined(VGP_arm_linux)
581 #       define UD2_4      .word 0xFFFFFFFF
582 #       define UD2_16     UD2_4    ; UD2_4    ; UD2_4    ; UD2_4
583 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
584 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
585 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
586 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
588         /* a leading page of unexecutable code */
589         UD2_PAGE
591 .global VG_(trampoline_stuff_start)
592 VG_(trampoline_stuff_start):
594 .global VG_(arm_linux_SUBST_FOR_sigreturn)
595 .type   VG_(arm_linux_SUBST_FOR_sigreturn),#function
596 VG_(arm_linux_SUBST_FOR_sigreturn):
597         mov r7, # __NR_sigreturn
598         svc #0
599         .long 0xFFFFFFFF /*illegal insn*/
600 .size VG_(arm_linux_SUBST_FOR_sigreturn), .-VG_(arm_linux_SUBST_FOR_sigreturn)
602 .global VG_(arm_linux_SUBST_FOR_rt_sigreturn)
603 .type   VG_(arm_linux_SUBST_FOR_rt_sigreturn),#function
604 VG_(arm_linux_SUBST_FOR_rt_sigreturn):
605         mov r7, # __NR_rt_sigreturn
606         svc #0
607         .long 0xFFFFFFFF /*illegal insn*/
608 .size VG_(arm_linux_SUBST_FOR_rt_sigreturn), .-VG_(arm_linux_SUBST_FOR_rt_sigreturn)
609         
610 .global VG_(arm_linux_REDIR_FOR_strlen)
611 VG_(arm_linux_REDIR_FOR_strlen):
612         mov     r2, r0
613         ldrb    r0, [r0, #0]    @ zero_extendqisi2
614         @ lr needed for prologue
615         cmp     r0, #0
616         bxeq    lr
617         mov     r0, #0
618 .L5:
619         add     r0, r0, #1
620         ldrb    r3, [r0, r2]    @ zero_extendqisi2
621         cmp     r3, #0
622         bne     .L5
623         bx      lr
624         UD2_4
626 .global VG_(arm_linux_REDIR_FOR_index)
627 VG_(arm_linux_REDIR_FOR_index):
628         ldrb    r3, [r0, #0]    @ zero_extendqisi2
629         and     r1, r1, #255
630         cmp     r3, r1
631         @ lr needed for prologue
632         bne     .L9
633         bx      lr
634 .L12:
635         ldrb    r3, [r0, #1]!   @ zero_extendqisi2
636         cmp     r3, r1
637         beq     .L11
638 .L9:
639         cmp     r3, #0
640         bne     .L12
641         mov     r0, #0
642         bx      lr
643 .L11:
644         bx      lr
645         UD2_4
647 .global VG_(arm_linux_REDIR_FOR_memcpy)
648 VG_(arm_linux_REDIR_FOR_memcpy):
649         stmfd   sp!, {r4, r5, lr}
650         subs    lr, r2, #0
651         mov     r5, r0
652         beq     .L2
653         cmp     r0, r1
654         bls     .L4
655         add     r3, r0, lr
656         add     r1, lr, r1
657         cmp     lr, #3
658         sub     r4, r3, #1
659         sub     r0, r1, #1
660         ble     .L28
661         sub     ip, r3, #5
662         sub     r1, r1, #5
663 .L8:
664         ldrb    r3, [r1, #4]    @ zero_extendqisi2
665         sub     lr, lr, #4
666         strb    r3, [ip, #4]
667         ldrb    r2, [r1, #3]    @ zero_extendqisi2
668         cmp     lr, #3
669         strb    r2, [ip, #3]
670         ldrb    r3, [r1, #2]    @ zero_extendqisi2
671         mov     r4, ip
672         strb    r3, [ip, #2]
673         ldrb    r2, [r1, #1]    @ zero_extendqisi2
674         mov     r0, r1
675         strb    r2, [ip, #1]
676         sub     r1, r1, #4
677         sub     ip, ip, #4
678         bgt     .L8
679         cmp     lr, #0
680         beq     .L2
681 .L28:
682         sub     r2, lr, #1
683 .L21:
684         sub     r2, r2, #1
685         ldrb    r3, [r0], #-1   @ zero_extendqisi2
686         cmn     r2, #1
687         strb    r3, [r4], #-1
688         bne     .L21
689 .L2:
690         mov     r0, r5
691         ldmfd   sp!, {r4, r5, pc}
692 .L4:
693         bcs     .L2
694         cmp     lr, #3
695         mov     ip, r0
696         ble     .L29
697 .L19:
698         ldrb    r3, [r1, #0]    @ zero_extendqisi2
699         sub     lr, lr, #4
700         strb    r3, [ip, #0]
701         ldrb    r2, [r1, #1]    @ zero_extendqisi2
702         cmp     lr, #3
703         strb    r2, [ip, #1]
704         ldrb    r3, [r1, #2]    @ zero_extendqisi2
705         strb    r3, [ip, #2]
706         ldrb    r2, [r1, #3]    @ zero_extendqisi2
707         add     r1, r1, #4
708         strb    r2, [ip, #3]
709         add     ip, ip, #4
710         bgt     .L19
711         cmp     lr, #0
712         beq     .L2
713 .L29:
714         sub     r2, lr, #1
715 .L20:
716         sub     r2, r2, #1
717         ldrb    r3, [r1], #1    @ zero_extendqisi2
718         cmn     r2, #1
719         strb    r3, [ip], #1
720         bne     .L20
721         mov     r0, r5
722         ldmfd   sp!, {r4, r5, pc}
723         UD2_4
725 .global VG_(arm_linux_REDIR_FOR_strcmp)
726 VG_(arm_linux_REDIR_FOR_strcmp):
727 .L64:
728         ldrb    r3, [r0], #1    @ zero_extendqisi2
729         ldrb    r2, [r1], #1    @ zero_extendqisi2
730         cmp     r3, #0
731         beq     .L67
732         cmp     r3, r2
733         beq     .L64
734         rsb     r0, r2, r3
735         bx      lr
736 .L67:
737         rsb     r0, r2, #0
738         bx      lr
739         UD2_4
741 .global VG_(trampoline_stuff_end)
742 VG_(trampoline_stuff_end):
744         /* and a trailing page of unexecutable code */
745         UD2_PAGE
747 #       undef UD2_4
748 #       undef UD2_16
749 #       undef UD2_64
750 #       undef UD2_256
751 #       undef UD2_1024
752 #       undef UD2_PAGE
753         
754 /*---------------- arm64-linux ----------------*/
755 #else
756 #if defined(VGP_arm64_linux)
758 #       define UD2_4      .word 0xFFFFFFFF
759 #       define UD2_16     UD2_4    ; UD2_4    ; UD2_4    ; UD2_4
760 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
761 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
762 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
763 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
765         /* a leading page of unexecutable code */
766         UD2_PAGE
768 .global VG_(trampoline_stuff_start)
769 VG_(trampoline_stuff_start):
771 .global VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
772 .type   VG_(arm64_linux_SUBST_FOR_rt_sigreturn),#function
773 VG_(arm64_linux_SUBST_FOR_rt_sigreturn):
774         mov x8, # __NR_rt_sigreturn
775         svc #0
776         .long 0xFFFFFFFF /*illegal insn*/
777 .size VG_(arm64_linux_SUBST_FOR_rt_sigreturn), \
778         .-VG_(arm64_linux_SUBST_FOR_rt_sigreturn)
780 .global VG_(arm64_linux_REDIR_FOR_strlen)
781 .type   VG_(arm64_linux_REDIR_FOR_strlen),#function
782 VG_(arm64_linux_REDIR_FOR_strlen):
783         mov     x2, x0
784         ldrb    w0, [x0]
785         cbz     w0, .L5
786         mov     x0, 0
787 .L4:
788         add     x0, x0, 1
789         ldrb    w1, [x2,x0]
790         cbnz    w1, .L4
791         ret
792 .L5:
793         mov     x0, 0
794         ret
795 .size VG_(arm64_linux_REDIR_FOR_strlen), .-VG_(arm64_linux_REDIR_FOR_strlen)
797 .global VG_(arm64_linux_REDIR_FOR_index)
798 .type   VG_(arm64_linux_REDIR_FOR_index),#function
799 VG_(arm64_linux_REDIR_FOR_index):
800         ldrb    w2, [x0]
801         uxtb    w1, w1
802         cmp     w2, w1
803         beq     .L11
804 .L13:
805         cbz     w2, .L16
806         ldrb    w2, [x0,1]!
807         cmp     w2, w1
808         bne     .L13
809 .L11:
810         ret
811 .L16:
812         mov     x0, 0
813         ret
814 .size VG_(arm64_linux_REDIR_FOR_index), .-VG_(arm64_linux_REDIR_FOR_index)
816 .global VG_(arm64_linux_REDIR_FOR_strcmp)
817 .type   VG_(arm64_linux_REDIR_FOR_strcmp),#function
818 VG_(arm64_linux_REDIR_FOR_strcmp):
819         ldrb    w2, [x0]
820         ldrb    w3, [x1]
821         cmp     w2, w3
822         bcc     .L22
823 .L21:
824         bhi     .L25
825         cbz     w2, .L26
826         ldrb    w2, [x0,1]!
827         ldrb    w3, [x1,1]!
828         cmp     w2, w3
829         bcs     .L21
830 .L22:
831         mov     x0, -1
832         ret
833 .L25:
834         mov     x0, 1
835         ret
836 .L26:
837         mov     x0, 0
838         ret
839 .size VG_(arm64_linux_REDIR_FOR_strcmp), .-VG_(arm64_linux_REDIR_FOR_strcmp)
841 .global VG_(trampoline_stuff_end)
842 VG_(trampoline_stuff_end):
844         /* and a trailing page of unexecutable code */
845         UD2_PAGE
847 #       undef UD2_4
848 #       undef UD2_16
849 #       undef UD2_64
850 #       undef UD2_256
851 #       undef UD2_1024
852 #       undef UD2_PAGE
853         
854 /*---------------- x86-darwin ----------------*/
855 #else
856 #if defined(VGP_x86_darwin)
858         /* a leading page of unexecutable code */
859 .fill 2048, 2, 0x0b0f /* `ud2` */
861 .globl VG_(trampoline_stuff_start)
862 VG_(trampoline_stuff_start):
864 .globl VG_(x86_darwin_SUBST_FOR_sigreturn)
865 VG_(x86_darwin_SUBST_FOR_sigreturn):
866         /* XXX does this need to have any special form? (cf x86-linux
867         version) */
868         movl    $ __NR_DARWIN_FAKE_SIGRETURN, %eax
869         int     $0x80
870         ud2
872 .globl VG_(x86_darwin_REDIR_FOR_strlen)
873 VG_(x86_darwin_REDIR_FOR_strlen):
874         movl    4(%esp), %edx
875         movl    %edx, %eax
876         jmp     1f
878         incl    %eax
880         cmpb    $0, (%eax)
881         jne     0b
882         subl    %edx, %eax
883         ret
885 .globl VG_(x86_darwin_REDIR_FOR_strcat)
886 VG_(x86_darwin_REDIR_FOR_strcat):
887         pushl   %esi
888         movl    8(%esp), %esi
889         movl    12(%esp), %ecx
890         movl    %esi, %edx
891         jmp     1f
893         incl    %edx
895         cmpb    $0, (%edx)
896         jne     0b
898         movzbl  (%ecx), %eax
899         incl    %ecx
900         movb    %al, (%edx)
901         incl    %edx
902         testb   %al, %al
903         jne     2b
904         movl    %esi, %eax
905         popl    %esi
906         ret
909 .globl VG_(x86_darwin_REDIR_FOR_strcmp)
910 VG_(x86_darwin_REDIR_FOR_strcmp):
911         movl    4(%esp), %edx
912         movl    8(%esp), %ecx
913         jmp     1f
915         incl    %edx
916         incl    %ecx
918         movzbl  (%edx), %eax
919         testb   %al, %al
920         je      2f
921         cmpb    (%ecx), %al
922         je      0b
924         movzbl  (%ecx),%edx
925         movzbl  %al,%eax
926         subl    %edx, %eax
927         ret
930 .globl VG_(x86_darwin_REDIR_FOR_strcpy)
931 VG_(x86_darwin_REDIR_FOR_strcpy):
932         pushl   %ebp
933         movl    %esp, %ebp
934         pushl   %esi
935         movl    8(%ebp), %esi
936         movl    12(%ebp), %ecx
937         movl    %esi, %edx
938         jmp     1f
940         incl    %ecx
941         incl    %edx
943         movzbl  (%ecx), %eax
944         testb   %al, %al
945         movb    %al, (%edx)
946         jne     0b
947         movl    %esi, %eax
948         popl    %esi
949         leave
950         ret
952 .globl VG_(x86_darwin_REDIR_FOR_strlcat)
953 VG_(x86_darwin_REDIR_FOR_strlcat):
954         pushl   %ebp
955         movl    %esp, %ebp
956         pushl   %edi
957         pushl   %esi
958         subl    $16, %esp
959         movl    8(%ebp), %esi
960         movl    16(%ebp), %ecx
961         movl    %esi, %edx
962         leal    (%ecx,%esi), %eax
963         jmp     1f
965         incl    %edx
967         cmpl    %edx, %eax
968         je      2f
969         cmpb    $0, (%edx)
970         jne     0b
972         movl    %edx, %edi
973         subl    %esi, %edi
974         movl    %ecx, %esi
975         subl    %edi, %esi
976         je      3f
977         movl    12(%ebp), %eax
978         jmp     6f
980         movl    12(%ebp), %eax
981         movl    %eax, (%esp)
982         call    VG_(x86_darwin_REDIR_FOR_strlen)
983         jmp     7f
985         cmpl    $1, %esi
986         je      5f
987         movb    %cl, (%edx)
988         decl    %esi
989         incl    %edx
991         incl    %eax
993         movzbl  (%eax), %ecx
994         testb   %cl, %cl
995         jne     4b
996         movb    $0, (%edx)
997         subl    12(%ebp), %eax
999         addl    $16, %esp
1000         leal    (%edi,%eax), %eax
1001         popl    %esi
1002         popl    %edi
1003         leave
1004         ret
1005         
1006         
1007 .globl VG_(trampoline_stuff_end)
1008 VG_(trampoline_stuff_end):
1010         /* a trailing page of unexecutable code */
1011 .fill 2048, 2, 0x0b0f /* `ud2` */
1014 /*---------------- amd64-darwin ----------------*/
1015 #else
1016 #if defined(VGP_amd64_darwin)
1018         /* a leading page of unexecutable code */
1019 .fill 2048, 2, 0x0b0f /* `ud2` */
1021 .globl VG_(trampoline_stuff_start)
1022 VG_(trampoline_stuff_start):
1024 .globl VG_(amd64_darwin_SUBST_FOR_sigreturn)
1025 VG_(amd64_darwin_SUBST_FOR_sigreturn):
1026         /* XXX does this need to have any special form? (cf x86-linux
1027         version) */
1028         movq    $ __NR_DARWIN_FAKE_SIGRETURN, %rax
1029         syscall
1030         ud2
1032 .globl VG_(amd64_darwin_REDIR_FOR_strlen)
1033 VG_(amd64_darwin_REDIR_FOR_strlen):
1034         movq    %rdi, %rax
1035         jmp     1f
1037         incq    %rax
1039         cmpb    $0, (%rax)
1040         jne     0b
1041         subq    %rdi, %rax
1042         ret
1044 .globl VG_(amd64_darwin_REDIR_FOR_strcat)
1045 VG_(amd64_darwin_REDIR_FOR_strcat):
1046         movq    %rdi, %rdx
1047         jmp     1f
1049         incq    %rdx
1051         cmpb    $0, (%rdx)
1052         jne     0b
1054         movzbl  (%rsi), %eax
1055         incq    %rsi
1056         movb    %al, (%rdx)
1057         incq    %rdx
1058         testb   %al, %al
1059         jne     2b
1060         movq    %rdi, %rax
1061         ret
1064 .globl VG_(amd64_darwin_REDIR_FOR_strcmp)
1065 VG_(amd64_darwin_REDIR_FOR_strcmp):
1066         jmp     1f
1068         incq    %rdi
1069         incq    %rsi
1071         movzbl  (%rdi), %eax
1072         testb   %al, %al
1073         je      2f
1074         cmpb    (%rsi), %al
1075         je      0b
1077         movzbl  (%rsi), %edx
1078         movzbl  %al, %eax
1079         subl    %edx, %eax
1080         ret
1082 .globl VG_(amd64_darwin_REDIR_FOR_strcpy)
1083 VG_(amd64_darwin_REDIR_FOR_strcpy):
1084         pushq   %rbp
1085         movq    %rdi, %rdx
1086         movq    %rsp, %rbp
1087         jmp     1f
1089         incq    %rsi
1090         incq    %rdx
1092         movzbl  (%rsi), %eax
1093         testb   %al, %al
1094         movb    %al, (%rdx)
1095         jne     0b
1096         leave
1097         movq    %rdi, %rax
1098         ret
1099         
1100 .globl VG_(amd64_darwin_REDIR_FOR_strlcat)
1101 VG_(amd64_darwin_REDIR_FOR_strlcat):
1102         pushq   %rbp
1103         leaq    (%rdx,%rdi), %rax
1104         movq    %rdi, %rcx
1105         movq    %rsp, %rbp
1106         pushq   %rbx
1107         subq    $8, %rsp
1108         jmp     1f
1110         incq    %rcx
1112         cmpq    %rcx, %rax
1113         je      2f
1114         cmpb    $0, (%rcx)
1115         jne     0b
1117         movq    %rcx, %rbx
1118         subq    %rdi, %rbx
1119         movq    %rdx, %rdi
1120         subq    %rbx, %rdi
1121         je      3f
1122         movq    %rsi, %rax
1123         jmp     6f
1125         movq    %rsi, %rdi
1126         call    VG_(amd64_darwin_REDIR_FOR_strlen)
1127         jmp     7f
1129         cmpq    $1, %rdi
1130         je      5f
1131         movb    %dl, (%rcx)
1132         decq    %rdi
1133         incq    %rcx
1135         incq    %rax
1137         movzbl  (%rax), %edx
1138         testb   %dl, %dl
1139         jne     4b
1140         movb    $0, (%rcx)
1141         subq    %rsi, %rax
1143         leaq    (%rbx,%rax), %rax
1144         addq    $8, %rsp
1145         popq    %rbx
1146         leave
1147         ret
1149 .globl VG_(amd64_darwin_REDIR_FOR_arc4random)
1150 VG_(amd64_darwin_REDIR_FOR_arc4random):
1151         /* not very random, hope dyld won't mind */
1152         movq    $0x76616c6772696e64, %rax
1153         ret
1155 .globl VG_(amd64_darwin_REDIR_FOR_strchr)
1156 VG_(amd64_darwin_REDIR_FOR_strchr):
1157         pushq   %rbp
1158         movq    %rsp, %rbp
1159         movb    (%rdi), %cl
1160         cmpb    %sil, %cl
1161         jne     1f
1162         movq    %rdi, %rax
1163         popq    %rbp
1164         ret
1166         testb   %cl, %cl
1167         movl    $0, %eax
1168         je      2f
1169         movb    1(%rdi), %cl
1170         incq    %rdi
1171         cmpb    %sil, %cl
1172         movq    %rdi, %rax
1173         jne     1b
1175         popq    %rbp
1176         ret
1177         
1178 .globl VG_(trampoline_stuff_end)
1179 VG_(trampoline_stuff_end):
1181         /* a trailing page of unexecutable code */
1182 .fill 2048, 2, 0x0b0f /* `ud2` */
1185 /*---------------- s390x-linux ----------------*/
1186 #else
1187 #if defined(VGP_s390x_linux)
1189         /* a leading page of unexecutable code */
1190         .fill 2048, 2, 0x0000
1192 .global VG_(trampoline_stuff_start)
1193 VG_(trampoline_stuff_start):
1195 .global VG_(s390x_linux_SUBST_FOR_sigreturn)
1196 VG_(s390x_linux_SUBST_FOR_sigreturn):
1197         svc __NR_sigreturn
1198         .short 0
1200 .global VG_(s390x_linux_SUBST_FOR_rt_sigreturn)
1201 VG_(s390x_linux_SUBST_FOR_rt_sigreturn):
1202         /* Old gcc unwinding code checks for a sig(_rt)_return svc and then
1203            for ra = cfa to decide if it is a sig_rt_frame or not. Since we
1204            set ra to this trampoline, but the cfa is still in the stack,
1205            the unwinder thinks, that this is a non-rt frame  and causes a
1206            crash in the gcc unwinder - which is used by the thread library
1207            and others. Therefore we add a lr 1,1 nop, to let the gcc
1208            unwinder bail out gracefully. This might also affect unwinding
1209            across the signal frame - tough luck. fixs390 */
1210         lr 1,1
1211         svc __NR_rt_sigreturn
1212         .short 0
1214 .global VG_(s390x_linux_REDIR_FOR_index)
1215 .type   VG_(s390x_linux_REDIR_FOR_index),@function
1216 VG_(s390x_linux_REDIR_FOR_index):
1218 #   %r2 = address of string
1219 #   %r3 = character to find
1221         lghi    %r0,255
1222         ngr     %r0,%r3        # r0 = (unsigned char)r3
1223         lghi    %r4,0
1224 .L1:
1225         llgc    %r1,0(%r2)     # r1 = byte from string
1226         cr      %r1,%r0        # compare
1227         ber     %r14           # return if found
1228         cr      %r1,%r4        # end of string ?
1229         je      .L2
1230         aghi    %r2,1          # increment r2
1231         j       .L1
1232 .L2:    lghi    %r2,0          # return value 0
1233         br      %r14
1234 .size VG_(s390x_linux_REDIR_FOR_index), .-VG_(s390x_linux_REDIR_FOR_index)
1236 .globl VG_(trampoline_stuff_end)
1237 VG_(trampoline_stuff_end):
1238         .fill 2048, 2, 0x0000
1240 /*---------------------- mips32-linux ----------------------*/
1241 #else
1242 #if defined(VGP_mips32_linux)
1244 #       define UD2_16     trap ; trap ; trap; trap
1245 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
1246 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
1247 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
1248 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
1251 .global VG_(trampoline_stuff_start)
1252 VG_(trampoline_stuff_start):
1254 .global VG_(mips32_linux_SUBST_FOR_sigreturn)
1255 VG_(mips32_linux_SUBST_FOR_sigreturn):
1256         li $v0,__NR_sigreturn
1257         syscall
1258         nop
1259         .long 0 /*illegal insn*/
1261 .global VG_(mips32_linux_SUBST_FOR_rt_sigreturn)
1262 VG_(mips32_linux_SUBST_FOR_rt_sigreturn):
1263         li $v0,__NR_rt_sigreturn
1264         syscall
1265         nop
1266         .long 0 /*illegal insn*/
1267         
1268 /* There's no particular reason that this needs to be handwritten
1269    assembly, but since that's what this file contains, here's a
1270    simple index() and strlen() implementations.
1273 .set push
1274 .set noreorder
1276 .global VG_(mips32_linux_REDIR_FOR_index)
1277 .type   VG_(mips32_linux_REDIR_FOR_index), @function
1278 VG_(mips32_linux_REDIR_FOR_index):
1279       move $v0, $a0
1280    index_loop:
1281       lbu $t0, 0($v0)
1282       beq $t0, $a1, index_end
1283       nop
1284       bne $t0, $zero, index_loop
1285       addiu $v0, $v0, 1
1286       move $v0, $zero
1287    index_end:
1288       jr $ra
1289       nop
1290 .size VG_(mips32_linux_REDIR_FOR_index), .-VG_(mips32_linux_REDIR_FOR_index)
1292 .global VG_(mips32_linux_REDIR_FOR_strlen)
1293 .type   VG_(mips32_linux_REDIR_FOR_strlen), @function
1294 VG_(mips32_linux_REDIR_FOR_strlen):
1295       move $v0, $a0
1296    strlen_loop:
1297       lbu $t0, 0($a0)
1298       bne $t0, $zero, strlen_loop
1299       addiu $a0, $a0, 1
1300       subu $v0, $a0, $v0
1301       jr $ra
1302       addiu $v0, $v0, -1
1303 .size VG_(mips32_linux_REDIR_FOR_strlen), .-VG_(mips32_linux_REDIR_FOR_strlen)
1305 .set pop
1307 .global VG_(trampoline_stuff_end)
1308 VG_(trampoline_stuff_end):
1311 #       undef UD2_16
1312 #       undef UD2_64
1313 #       undef UD2_256
1314 #       undef UD2_1024
1315 #       undef UD2_PAGE
1317 /*---------------------- nanomips-linux --------------------*/
1318 #else
1319 #if defined(VGP_nanomips_linux)
1321 .global VG_(trampoline_stuff_start)
1322 VG_(trampoline_stuff_start):
1324 .set push
1325 .set noreorder
1327 .global VG_(nanomips_linux_SUBST_FOR_rt_sigreturn)
1328 VG_(nanomips_linux_SUBST_FOR_rt_sigreturn):
1329    li $t4, __NR_rt_sigreturn
1330    syscall[32]
1331    .long 0
1333 .global VG_(nanomips_linux_REDIR_FOR_index)
1334 .type   VG_(nanomips_linux_REDIR_FOR_index), @function
1335 VG_(nanomips_linux_REDIR_FOR_index):
1336    index_loop:
1337       lbu $t0, 0($a0)
1338       beqc $t0, $a1, index_end
1339       addiu $a0, $a0, 1
1340       bnec $t0, $zero, index_loop
1341       move $a0, $zero
1342    index_end:
1343       jrc $ra
1344 .size VG_(nanomips_linux_REDIR_FOR_index), .-VG_(nanomips_linux_REDIR_FOR_index)
1346 .global VG_(nanomips_linux_REDIR_FOR_strlen)
1347 .type   VG_(nanomips_linux_REDIR_FOR_strlen), @function
1348 VG_(nanomips_linux_REDIR_FOR_strlen):
1349       move $t1, $a0
1350    strlen_loop:
1351       lbu $t0, 0($a0)
1352       addiu $a0, $a0, 1
1353       bnec $t0, $zero, strlen_loop
1354       subu $a0, $a0, $t1
1355       addiu $a0, $a0, -1
1356       jrc $ra
1358 .size VG_(nanomips_linux_REDIR_FOR_strlen), .-VG_(nanomips_linux_REDIR_FOR_strlen)
1360 .set pop
1362 .global VG_(trampoline_stuff_end)
1363 VG_(trampoline_stuff_end):
1366 /*---------------------- mips64-linux ----------------------*/
1367 #else
1368 #if defined(VGP_mips64_linux)
1370 #       define UD2_16     trap ; trap ; trap; trap
1371 #       define UD2_64     UD2_16   ; UD2_16   ; UD2_16   ; UD2_16
1372 #       define UD2_256    UD2_64   ; UD2_64   ; UD2_64   ; UD2_64
1373 #       define UD2_1024   UD2_256  ; UD2_256  ; UD2_256  ; UD2_256
1374 #       define UD2_PAGE   UD2_1024 ; UD2_1024 ; UD2_1024 ; UD2_1024  
1376 .global VG_(trampoline_stuff_start)
1377 VG_(trampoline_stuff_start):
1379 .global VG_(mips64_linux_SUBST_FOR_rt_sigreturn)
1380 VG_(mips64_linux_SUBST_FOR_rt_sigreturn):
1381         li $2,__NR_rt_sigreturn
1382         syscall
1383         nop
1384         .long 0 /*illegal insn*/
1386 /* There's no particular reason that this needs to be handwritten
1387    assembly, but since that's what this file contains, here's a
1388    simple index() and strlen() implementations.
1391 .set push
1392 .set noreorder
1394 .global VG_(mips64_linux_REDIR_FOR_index)
1395 .type   VG_(mips64_linux_REDIR_FOR_index), @function
1396 VG_(mips64_linux_REDIR_FOR_index):
1397       move $v0, $a0
1398    index_loop:
1399       lbu $t0, 0($v0)
1400       beq $t0, $a1, index_end
1401       nop
1402       bne $t0, $zero, index_loop
1403       daddiu $v0, $v0, 1
1404       move $v0, $zero
1405    index_end:
1406       jr $ra
1407       nop
1408 .size VG_(mips64_linux_REDIR_FOR_index), .-VG_(mips64_linux_REDIR_FOR_index)
1410 .global VG_(mips64_linux_REDIR_FOR_strlen)
1411 .type   VG_(mips64_linux_REDIR_FOR_strlen), @function
1412 VG_(mips64_linux_REDIR_FOR_strlen):
1413       move $v0, $a0
1414    strlen_loop:
1415       lbu $t0, 0($a0)
1416       bne $t0, $zero, strlen_loop
1417       daddiu $a0, $a0, 1
1418       dsubu $v0, $a0, $v0
1419       jr $ra
1420       daddiu $v0, $v0, -1
1421 .size VG_(mips64_linux_REDIR_FOR_strlen), .-VG_(mips64_linux_REDIR_FOR_strlen)
1423 .set pop
1425 .global VG_(trampoline_stuff_end)
1426 VG_(trampoline_stuff_end):
1429 #       undef UD2_16
1430 #       undef UD2_64
1431 #       undef UD2_256
1432 #       undef UD2_1024
1433 #       undef UD2_PAGE
1435 /*---------------- x86-solaris ----------------*/
1436 #else
1437 #if defined(VGP_x86_solaris)
1439 .global VG_(trampoline_stuff_start)
1440 VG_(trampoline_stuff_start):
1442 /* int strcmp(const char *s1, const char *s2); */
1443 .global VG_(x86_solaris_REDIR_FOR_strcmp)
1444 .type   VG_(x86_solaris_REDIR_FOR_strcmp), @function
1445 VG_(x86_solaris_REDIR_FOR_strcmp):
1446         pushl   %ebp                    /* establish a stack frame */
1447         movl    %esp, %ebp
1448         movl    8(%ebp), %edx           /* get s1 */
1449         movl    12(%esp), %ecx          /* get s2 */
1450         jmp     2f                      /* go compare the first characters */
1452         incl    %edx                    /* skip to the next s1 character */
1453         incl    %ecx                    /* skip to the next s2 character */
1455         movzbl  (%edx), %eax            /* load a character from s1 */
1456         testb   %al, %al                /* is it null? */
1457         jz      3f                      /* yes, exit */
1458         cmpb    (%ecx), %al             /* are the characters equal? */
1459         je      1b                      /* yes, proceed with next characters */
1461         movzbl  (%ecx), %edx            /* load a character from s2 */
1462         subl    %edx, %eax              /* calculate the return value */
1463         popl    %ebp                    /* destroy the stack frame */
1464         ret                             /* return to the caller */
1465 .size VG_(x86_solaris_REDIR_FOR_strcmp), .-VG_(x86_solaris_REDIR_FOR_strcmp)
1467 /* size_t strlen(const char *s); */
1468 .global VG_(x86_solaris_REDIR_FOR_strlen)
1469 .type   VG_(x86_solaris_REDIR_FOR_strlen), @function
1470 VG_(x86_solaris_REDIR_FOR_strlen):
1471         pushl   %ebp                    /* establish a stack frame */
1472         movl    %esp, %ebp
1473         movl    8(%ebp), %edx           /* get s */
1474         movl    %edx, %eax              /* copy s */
1475         jmp     2f                      /* go handle the first character */
1477         incl    %eax                    /* skip to the next s character */
1479         cmpb    $0, (%eax)              /* is the s character null? */
1480         jne     1b                      /* no, go process the next character */
1481         subl    %edx, %eax              /* calculate the return value */
1482         popl    %ebp                    /* destroy the stack frame */
1483         ret                             /* return to the caller */
1484 .size VG_(x86_solaris_REDIR_FOR_strlen), .-VG_(x86_solaris_REDIR_FOR_strlen)
1486 .global VG_(trampoline_stuff_end)
1487 VG_(trampoline_stuff_end):
1489 /*---------------- amd64-solaris ----------------*/
1490 #else
1491 #if defined(VGP_amd64_solaris)
1493 .global VG_(trampoline_stuff_start)
1494 VG_(trampoline_stuff_start):
1496 /* char *strcpy(char *restrict s1, const char *restrict s2); */
1497 .global VG_(amd64_solaris_REDIR_FOR_strcpy)
1498 .type   VG_(amd64_solaris_REDIR_FOR_strcpy), @function
1499 VG_(amd64_solaris_REDIR_FOR_strcpy):
1500         pushq   %rbp                    /* establish a stack frame */
1501         movq    %rsp, %rbp
1502         movq    %rdi, %rdx              /* copy s1 */
1504         movzbl  (%rsi), %eax            /* load one input character */
1505         movb    %al, (%rdx)             /* copy to output/s1 */
1506         incq    %rsi                    /* skip to the next output character */
1507         incq    %rdx                    /* skip to the next input character */
1508         testb   %al, %al                /* is the copied character null? */
1509         jnz     1b                      /* no, copy the next character */
1510         leave                           /* destroy the stack frame */
1511         movq    %rdi, %rax              /* set s1 as the return value */
1512         ret                             /* return to the caller */
1513 .size VG_(amd64_solaris_REDIR_FOR_strcpy), .-VG_(amd64_solaris_REDIR_FOR_strcpy)
1515 /* char *strncpy(char *restrict s1, const char *restrict s2, size_t n); */
1516 .global VG_(amd64_solaris_REDIR_FOR_strncpy)
1517 .type   VG_(amd64_solaris_REDIR_FOR_strncpy), @function
1518 VG_(amd64_solaris_REDIR_FOR_strncpy):
1519         pushq   %rbp                    /* establish a stack frame */
1520         movq    %rsp, %rbp
1521         movq    %rdi, %rcx              /* copy s1 */
1523         testq   %rdx, %rdx              /* is the remaining size zero? */
1524         jz      3f                      /* yes, all done */
1525         movzbl  (%rsi), %eax            /* load one input character */
1526         movb    %al, (%rcx)             /* copy to output/s1 */
1527         decq    %rdx                    /* decrement the remaining size */
1528         incq    %rsi                    /* skip to the next output character */
1529         incq    %rcx                    /* skip to the next input character */
1530         testb   %al, %al                /* is the copied character null? */
1531         jnz     1b                      /* no, copy the next character */
1533         testq   %rdx, %rdx              /* is the remaining size zero? */
1534         jz      3f                      /* yes, all done */
1535         movb    $0, (%rdx)              /* copy null to output/s2 */
1536         decq    %rdx                    /* decrement the remaining size */
1537         incq    %rsi                    /* skip to next output character */
1538         jmp     2b                      /* proceed with the next character */
1540         leave                           /* destroy the stack frame */
1541         movq    %rdi, %rax              /* set s1 as the return value */
1542         ret                             /* return to the caller */
1543 .size VG_(amd64_solaris_REDIR_FOR_strncpy), .-VG_(amd64_solaris_REDIR_FOR_strncpy)
1545 /* int strcmp(const char *s1, const char *s2); */
1546 .global VG_(amd64_solaris_REDIR_FOR_strcmp)
1547 .type   VG_(amd64_solaris_REDIR_FOR_strcmp), @function
1548 VG_(amd64_solaris_REDIR_FOR_strcmp):
1549         pushq   %rbp                    /* establish a stack frame */
1550         movq    %rsp, %rbp
1551         jmp     2f                      /* go compare the first characters */
1553         incq    %rdi                    /* skip to the next s1 character */
1554         incq    %rsi                    /* skip to the next s2 character */
1556         movzbl  (%rdi), %eax            /* load a character from s1 */
1557         testb   %al, %al                /* is it null? */
1558         jz      3f                      /* yes, exit */
1559         cmpb    (%rsi), %al             /* are the characters equal? */
1560         je      1b                      /* yes, proceed with next characters */
1562         movzbl  (%rsi), %edx            /* load a character from s2 */
1563         subl    %edx, %eax              /* calculate the return value */
1564         leave                           /* destroy the stack frame */
1565         ret                             /* return to the caller */
1566 .size VG_(amd64_solaris_REDIR_FOR_strcmp), .-VG_(amd64_solaris_REDIR_FOR_strcmp)
1568 /* char *strcat(char *restrict s1, const char *restrict s2); */
1569 .global VG_(amd64_solaris_REDIR_FOR_strcat)
1570 .type   VG_(amd64_solaris_REDIR_FOR_strcat), @function
1571 VG_(amd64_solaris_REDIR_FOR_strcat):
1572         pushq   %rbp                    /* establish a stack frame */
1573         movq    %rsp, %rbp
1574         movq    %rdi, %rdx              /* copy s1 */
1575         jmp     2f                      /* go handle the first character */
1577         incq    %rdx                    /* skip to the next s1 character */
1579         cmpb    $0, (%rdx)              /* is the s1 character null? */
1580         jne     1b                      /* no, go check the next character */
1582         movzbl  (%rsi), %eax            /* load a character from s2 */
1583         movb    %al, (%rdx)             /* copy the s2 character to s1 */
1584         incq    %rdx                    /* skip to the next s1 character */
1585         incq    %rsi                    /* skip to the next s2 character */
1586         testb   %al, %al                /* was the character null? */
1587         jnz     3b                      /* no, go copy the next character */
1588         movq    %rdi, %rax              /* set s1 as the return value */
1589         leave                           /* destroy the stack frame */
1590         ret                             /* return to the caller */
1591 .size VG_(amd64_solaris_REDIR_FOR_strcat), .-VG_(amd64_solaris_REDIR_FOR_strcat)
1593 /* size_t strlen(const char *s); */
1594 .global VG_(amd64_solaris_REDIR_FOR_strlen)
1595 .type   VG_(amd64_solaris_REDIR_FOR_strlen), @function
1596 VG_(amd64_solaris_REDIR_FOR_strlen):
1597         pushq   %rbp                    /* establish a stack frame */
1598         movq    %rsp, %rbp
1599         movq    %rdi, %rax              /* copy s */
1600         jmp     2f                      /* go handle the first character */
1602         incq    %rax                    /* skip to the next s character */
1604         cmpb    $0, (%rax)              /* is the s character null? */
1605         jne     1b                      /* no, go process the next character */
1606         subq    %rdi, %rax              /* calculate the return value */
1607         leave                           /* destroy the stack frame */
1608         ret                             /* return to the caller */
1609 .size VG_(amd64_solaris_REDIR_FOR_strlen), .-VG_(amd64_solaris_REDIR_FOR_strlen)
1611 .global VG_(trampoline_stuff_end)
1612 VG_(trampoline_stuff_end):
1614 /*---------------- unknown ----------------*/
1615 #else
1616 #  error Unknown platform
1618 #endif
1619 #endif
1620 #endif
1621 #endif
1622 #endif
1623 #endif
1624 #endif
1625 #endif
1626 #endif
1627 #endif
1628 #endif
1629 #endif
1630 #endif
1631 #endif
1633 /* Let the linker know we don't need an executable stack */
1634 MARK_STACK_NO_EXEC
1636 /*--------------------------------------------------------------------*/
1637 /*--- end                                                          ---*/
1638 /*--------------------------------------------------------------------*/