Add a test program for the membarrier() system call
[valgrind.git] / exp-bbv / tests / amd64-linux / ll.S
blob8f446063b6b3458fceb3a61bd131273e76bf3572
2 #  linux_logo in x86_64 assembly language
3 #    based on the code from ll_asm-0.36
5 #  By Vince Weaver <vince _at_ deater.net>
7 # Modified to remove non-deterministic system calls
8 # And to avoid reading from /proc
11                 
12 .include "logo.include"
14 # offsets into the results returned by the uname syscall
15 .equ U_SYSNAME,0
16 .equ U_NODENAME,65
17 .equ U_RELEASE,65*2
18 .equ U_VERSION,(65*3)
19 .equ U_MACHINE,(65*4)
20 .equ U_DOMAINNAME,65*5
22 # offset into the results returned by the sysinfo syscall
23 .equ S_TOTALRAM,32
25 # Sycscalls
26 .equ SYSCALL_EXIT,    60
27 .equ SYSCALL_READ,     0
28 .equ SYSCALL_WRITE,    1
29 .equ SYSCALL_OPEN,     2
30 .equ SYSCALL_CLOSE,    3
31 .equ SYSCALL_SYSINFO, 99
32 .equ SYSCALL_UNAME,   63
35 .equ STDIN,0
36 .equ STDOUT,1
37 .equ STDERR,2
39         .globl _start   
40 _start: 
41         #=========================
42         # PRINT LOGO
43         #=========================
45 # LZSS decompression algorithm implementation
46 # by Stephan Walter 2002, based on LZSS.C by Haruhiko Okumura 1989
47 # optimized some more by Vince Weaver
49         # we used to fill the buffer with FREQUENT_CHAR
50         # but, that only gains us one byte of space in the lzss image.
51         # the lzss algorithm does automatic RLE... pretty clever
52         # so we compress with NUL as FREQUENT_CHAR and it is pre-done for us
54         mov     $(N-F), %ebp            # R
56         mov     $logo, %esi             # %esi points to logo (for lodsb)
58         mov     $out_buffer, %edi       # point to out_buffer
59         push    %rdi                    # save this value for later
61         xor     %ecx, %ecx
63 decompression_loop:     
64         lodsb                   # load in a byte
66         mov     $0xff, %bh      # re-load top as a hackish 8-bit counter
67         mov     %al, %bl        # move in the flags
69 test_flags:
70         cmp     $logo_end, %esi # have we reached the end?
71         je      done_logo       # ! if so, exit
73         shr     $1, %ebx        # shift bottom bit into carry flag
74         jc      discrete_char   # ! if set, we jump to discrete char
76 offset_length:
77         lodsw                   # get match_length and match_position
78         mov %eax,%edx           # copy to edx
79                                 # no need to mask dx, as we do it
80                                 # by default in output_loop
81         
82         shr $(P_BITS),%eax      
83         add $(THRESHOLD+1),%al
84         mov %al,%cl             # cl = (ax >> P_BITS) + THRESHOLD + 1
85                                   #                       (=match_length)
86                 
87 output_loop:
88         and     $POSITION_MASK,%dh      # mask it
89         mov     text_buf(%rdx), %al     # load byte from text_buf[]
90         inc     %edx                    # advance pointer in text_buf
91 store_byte:     
92         stosb                           # store it
93         
94         mov     %al, text_buf(%rbp)     # store also to text_buf[r]
95         inc     %ebp                    # r++
96         and     $(N-1), %bp             # mask r
98         loop    output_loop             # repeat until k>j
99         
100         or      %bh,%bh                 # ! if 0 we shifted through 8 and must
101         jnz     test_flags              # re-load flags
102         
103         jmp     decompression_loop
105 discrete_char:
106         lodsb                           # load a byte
107         inc     %ecx                    # we set ecx to one so byte
108                                         # will be output once
109                                         # (how do we know ecx is zero?)
110                                         
111         jmp     store_byte              # and cleverly store it
114 # end of LZSS code
116 done_logo:
118         pop     %rbp                    # get out_buffer and keep in bp
119         mov     %ebp,%ecx               # move out_buffer to ecx
121         call    write_stdout            # print the logo
123         #
124         #  Setup
125         #
126 setup:
127         mov     $strcat,%edx            # use rdx as call pointer (smaller op)
129         
130         #==========================
131         # PRINT VERSION
132         #==========================
133         
134 #       push    $SYSCALL_UNAME          # uname syscall
135 #       pop     %rax                    # in 3 bytes    
136         mov     $uname_info,%edi        # uname struct (0 extend address)
137 #       syscall                         # do syscall
139         mov     %ebp,%edi               # point %edi to out_buffer
140                 
141         mov     $(uname_info+U_SYSNAME),%esi    # os-name from uname "Linux"
142         call    *%rdx                   # call strcat
144         mov     $ver_string,%esi                # source is " Version "
145         call    *%rdx                           # call strcat
146         push    %rsi                            # save our .txt pointer
147         
148         mov     $(uname_info+U_RELEASE),%esi    # version from uname "2.4.1"
149         call    *%rdx                           # call strcat
150         
151         pop     %rsi                    # restore .txt pointer
152                                         # source is ", Compiled "
153         call    *%rdx                   # call strcat
154         push    %rsi                    # store for later
156         mov     $(uname_info+U_VERSION),%esi    # compiled date
157         call    *%rdx                   # call strcat
159         mov     %ebp,%ecx               # move out_buffer to ecx
161         mov     $0xa,%ax                # store linefeed on end
162         stosw                           # and zero                        
164         call    *%rdx                   # call strcat
165         
166         call    center_and_print        # center and print
168         #===============================
169         # Middle-Line
170         #===============================
171 middle_line:            
172         #=========
173         # Load /proc/cpuinfo into buffer
174         #=========
176         push    %rdx                    # save call pointer
178 #       push    $SYSCALL_OPEN           # load 5 [ open() ]
179 #       pop     %rax                    # in 3 bytes
180         
181 #       mov     $cpuinfo,%edi           # '/proc/cpuinfo'
182 #       xor     %esi,%esi               # 0 = O_RDONLY <bits/fcntl.h>
183 #       cdq                             # clear edx in clever way
184 #       syscall                         # syscall.  fd in eax.  
185                                         # we should check that eax>=0
186                                         
187 #       mov     %eax,%edi               # save our fd
188         
189 #       xor     %eax,%eax               # SYSCALL_READ make== 0
191         mov     $disk_buffer,%esi
193 #       mov     $16,%dh                 # 4096 is maximum size of proc file #)
194                                         # we load sneakily by knowing
195                                         # 16<<8 = 4096. be sure edx clear
197 #       syscall
199 #       push    $SYSCALL_CLOSE          # close (to be correct)
200 #       pop     %rax
201 #       syscall                 
203         #=============
204         # Number of CPUs
205         #=============
206 number_of_cpus:
208         xor     %ebx,%ebx               # chip count
209         
210                                         # $disk_buffer still in %rsi
211 bogo_loop:      
212         mov     (%rsi), %eax            # load 4 bytes into eax
213         inc     %esi                    # increment pointer
214         
215         cmp     $0,%al                  # check for end of file
216         je      done_bogo
217         
218         # Grrr, due to a bug in binutils 2.18.50.0.9
219         #   (which unfortunately shipped with Fedora 10)
220         #   http://sourceware.org/bugzilla/show_bug.cgi?id=6878
221         #   We can't use the apostrophe character
223 #       cmp     $('o'<<24+'g'<<16+'o'<<8+'b'),%eax
224         cmp     $(0x6f<<24+0x67<<16+0x6f<<8+0x62),%eax
225                                         # "bogo" in little-endian
226                                         
227         jne     bogo_loop               # ! if not equal, keep going
228         add     $2,%ebx                 # otherwise, we have a bogo
229                                         # 2 times too for future magic
230         jmp     bogo_loop
232 done_bogo:
233         lea     one-6(%rbx,%rbx,2), %esi        
234                                         # Load into esi
235                                         # [one]+(num_cpus*6)
236                                         #
237                                         # the above multiplies by three
238                                         # esi = (ebx+(ebx*2))
239                                         # and we double-incremented ebx 
240                                         # earlier
241          
242         mov     %ebp,%edi               # move output buffer to edi
244         pop     %rdx                    # restore call pointer
245         call    *%rdx                   # copy it (call strcat)
247 #       mov     $' ',%al                # print a space
248         mov     $0x20,%al               # print a space
249         
250         stosb
252         push %rbx
253         push %rdx                       # store strcat pointer
255         #=========
256         # MHz
257         #=========
258 print_mhz:
259 #       mov     $('z'<<24+'H'<<16+'M'<<8+' '),%ebx
260         mov     $(0x7a<<24+0x48<<16+0x4d<<8+0x20),%ebx
261                                         # find ' MHz' and grab up to .
262                                         # we are little endian
263 #       mov     $'.',%ah
264         mov     $0x2e,%ah
266         # below is same as "sub $(strcat-find_string),%edx
267         # gas won't let us force the one-byte constant
268         .byte 0x83,0xEA,strcat-find_string   
269         
270         call    *%rdx                   # call find string
272         mov     %ebx,%eax               # clever way to get MHz in, sadly
273         ror     $8,%eax                 # not any smaller than a mov
274         stosl                           
276         #=========
277         # Chip Name
278         #=========
279 chip_name:
280 #       mov     $('e'<<24+'m'<<16+'a'<<8+'n'),%ebx
281         mov     $(0x65<<24+0x6d<<16+0x61<<8+0x6e),%ebx
282                                         # find 'name\t: ' and grab up to \n
283                                         # we are little endian
284 #       mov     $' ',%ah
285         mov     $0x20,%ah
286         call    *%rdx                   # call find_string
287         stosb
288         call    skip_spaces
289         
290         pop     %rdx
291         pop     %rbx                    # restore chip count
292         pop     %rsi
293                                 
294         call    *%rdx                   # ' Processor'
295         cmpb    $2,%bl
296         jne     print_s
297         inc     %rsi                    # ! if singular, skip the s
298 print_s:
299         call    *%rdx                   # 's, '
300         
301         push    %rsi                    # restore the values
302         push    %rdx
303                         
304         #========
305         # RAM
306         #========
308 #       push    %rdi    
309 #       push    $SYSCALL_SYSINFO        # sysinfo() syscall
310 #       pop     %rax    
311 #       mov     $sysinfo_buff,%edi
312 #       syscall
313 #       pop     %rdi
315         # The following has to be a 64 bit load, to support
316         # Ram > 4GB
317         mov     (sysinfo_buff+S_TOTALRAM),%rax  # size in bytes of RAM
318         shr     $20,%rax                # divide by 1024*1024 to get M
319         adc     $0, %eax                # round 
321         call num_to_ascii
322         
323         pop  %rdx                       # restore strcat pointer
324         
325         pop     %rsi                    # print 'M RAM, '
326         call    *%rdx                   # call strcat
328         push    %rsi
329         
330         #========
331         # Bogomips
332         #========
333         
334 #       mov     $('s'<<24+'p'<<16+'i'<<8+'m'),%ebx
335         mov     $(0x73<<24+0x70<<16+0x69<<8+0x6d),%ebx
336                                         # find 'mips\t: ' and grab up to \n
337         mov     $0xa,%ah
338         call    find_string
340         pop     %rsi                    # bogo total follows RAM 
342         call    *%rdx                   # call strcat
344         push    %rsi
346         mov     %ebp,%ecx               # point ecx to out_buffer
348         push    %rcx
349         call    center_and_print        # center and print
351         #=================================
352         # Print Host Name
353         #=================================
354 last_line:
355         mov     %ebp,%edi               # point to output_buffer
356         
357         mov     $(uname_info+U_NODENAME),%esi   # host name from uname()
358         call    *%rdx                   # call strcat
360         pop     %rcx                    # ecx is unchanged
361         call    center_and_print        # center and print
362         
363         pop     %rcx                    # (.txt) pointer to default_colors
364         
365         call    write_stdout
367         #================================
368         # Exit
369         #================================
370 exit:
371         push    $SYSCALL_EXIT           # Put exit syscall in rax
372         pop     %rax
374         xor     %edi,%edi               # Make return value $0
375         syscall
378         #=================================
379         # FIND_STRING 
380         #=================================
381         #   ah is char to end at
382         #   ebx is 4-char ascii string to look for
383         #   edi points at output buffer
385 find_string:
386                                         
387         mov     $disk_buffer-1,%esi     # look in cpuinfo buffer
388 find_loop:
389         inc     %esi
390         cmpb    $0, (%rsi)              # are we at EOF?
391         je      done                    # ! if so, done
393         cmp     (%rsi), %ebx            # do the strings match?
394         jne     find_loop               # ! if not, loop
395         
396                                         # ! if we get this far, we matched
398 find_colon:
399         lodsb                           # repeat till we find colon
400         cmp     $0,%al
401         je      done
402 #       cmp     $':',%al
403         cmp     $0x3a,%al       
404         jne     find_colon
406 skip_spaces:            
407         lodsb                           # skip spaces
408         cmp     $0x20,%al               # Loser new intel chips have lots??
409         je      skip_spaces
410         
411 store_loop:      
412         cmp     $0,%al
413         je      done
414         cmp     %ah,%al                 # is it end string?
415         je      almost_done             # ! if so, finish
416 #       cmp     $'\n',%al
417         cmp     $0xa,%al
418         je      almost_done
419         stosb                           # ! if not store and continue
420         lodsb
421         
422         jmp     store_loop
423          
424 almost_done:     
425         movb     $0, (%rdi)             # replace last value with NUL 
426 done:
427         ret
430         #================================
431         # strcat
432         #================================
434 strcat:
435         lodsb                           # load a byte from [ds:esi]
436         stosb                           # store a byte to [es:edi]
437         cmp     $0,%al                  # is it zero?
438         jne     strcat                  # ! if not loop
439         dec     %edi                    # point to one less than null
440         ret                             # return
442         #==============================
443         # center_and_print
444         #==============================
445         # string to center in ecx
447 center_and_print:
448         push    %rdx                    # save strcat pointer
449         push    %rcx                    # save the string pointer
450         inc     %edi                    # move to a clear buffer
451         push    %rdi                    # save for later
453 #       mov     $('['<<8+27),%ax        # we want to output ^[[
454         mov     $(0x5b<<8+27),%ax       # we want to output ^[[ 
455         stosw
457         cdq                             # clear dx
458         
459 str_loop2:                              # find end of string    
460         inc     %edx
461         cmpb    $0,(%rcx,%rdx)          # repeat till we find zero
462         jne     str_loop2
463         
464         push    $81                     # one added to cheat, we don't
465                                         # count the trailing '\n'
466         pop     %rax
467         
468         cmp     %eax,%edx               # see if we are >=80
469         jl      not_too_big             # ! if so, don't center
470         push    $80
471         pop     %rdx
472         
473 not_too_big:                    
474         sub     %edx,%eax               # subtract size from 80
475         
476         shr     %eax                    # then divide by 2
477         
478         call    num_to_ascii            # print number of spaces
479 #       mov     $'C',%al                # tack a 'C' on the end
480         mov     $0x43,%al               # tack a 'C' on the end 
481                                         # ah is zero from num_to_ascii
482         stosw                           # store C and a NULL
483         pop  %rcx                       # pop the pointer to ^[[xC
484         
485         call write_stdout               # write to the screen
486         
487 done_center:
488         pop  %rcx                       # restore string pointer
489                                         # and trickily print the real string
491         pop %rdx                        # restore strcat pointer
493         #================================
494         # WRITE_STDOUT
495         #================================
496         # ecx has string
497         # eax,ebx,ecx,edx trashed
498 write_stdout:
499         push    %rdx
500         push    $SYSCALL_WRITE          # put 4 in eax (write syscall)
501         pop     %rax                    # in 3 bytes of code
502         
503         cdq                             # clear edx
504         
505         lea     1(%rdx),%edi            # put 1 in ebx (stdout)
506                                         # in 3 bytes of code
508         mov     %ecx,%esi
509         
510 str_loop1:
511         inc     %edx
512         cmpb    $0,(%rcx,%rdx)          # repeat till zero
513         jne     str_loop1
515         syscall                         # run the syscall
516         pop     %rdx
517         ret
519         ##############################
520         # num_to_ascii
521         ##############################
522         # ax = value to print
523         # edi points to where we want it
524         
525 num_to_ascii:
526         push    $10
527         pop     %rbx
528         xor     %ecx,%ecx       # clear ecx
529 div_by_10:
530         cdq                     # clear edx
531         div     %ebx            # divide
532         push    %rdx            # save for later
533         inc     %ecx            # add to length counter
534         or      %eax,%eax       # was Q zero?
535         jnz     div_by_10       # ! if not divide again
536         
537 write_out:
538         pop     %rax            # restore in reverse order
539         add     $0x30, %al      # convert to ASCII
540         stosb                   # save digit
541         loop    write_out       # loop till done
542         ret
544 #===========================================================================
545 #       section .data
546 #===========================================================================
547 .data
549 ver_string:     .ascii  " Version \0"
550 compiled_string:        .ascii  ", Compiled \0"
551 processor:              .ascii  " Processor\0"
552 s_comma:                .ascii  "s, \0"
553 ram_comma:      .ascii  "M RAM, \0"
554 bogo_total:     .ascii  " Bogomips Total\n\0"
556 default_colors: .ascii "\033[0m\n\n\0"
558 cpuinfo:        .ascii  "/proc/cpuinfo\0"
561 one:    .ascii  "One\0\0\0"
562 two:    .ascii  "Two\0\0\0"
563 three:  .ascii  "Three\0"
564 four:   .ascii  "Four\0"
566 .include        "logo.lzss_new"
568 disk_buffer:
569 .ascii "processor       : 0\n"
570 .ascii "vendor_id       : GenuineIntel\n"
571 .ascii "cpu family      : 15\n"
572 .ascii "model           : 6\n"
573 .ascii "model name      : Intel(R) Xeon(TM) CPU 3.46GHz\n"
574 .ascii "stepping        : 4\n"
575 .ascii "cpu MHz         : 3200.000\n"
576 .ascii "cache size      : 2048 KB\n"
577 .ascii "physical id     : 0\n"
578 .ascii "siblings        : 2\n"
579 .ascii "core id         : 0\n"
580 .ascii "cpu cores       : 2\n"
581 .ascii "apicid          : 0\n"
582 .ascii "initial apicid  : 0\n"
583 .ascii "fpu             : yes\n"
584 .ascii "fpu_exception   : yes\n"
585 .ascii "cpuid level     : 6\n"
586 .ascii "wp              : yes\n"
587 .ascii "flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc pebs bts pni dtes64 monitor ds_cpl vmx est cid cx16 xtpr pdcm lahf_lm tpr_shadow\n"
588 .ascii "bogomips        : 6934.38\n"
589 .ascii "clflush size    : 64\n"
590 .ascii "cache_alignment : 128\n"
591 .ascii "address sizes   : 36 bits physical, 48 bits virtual\n"
592 .ascii "power management:\n"
593 .ascii "\n"
594 .ascii "processor       : 1\n"
595 .ascii "vendor_id       : GenuineIntel\n"
596 .ascii "cpu family      : 15\n"
597 .ascii "model           : 6\n"
598 .ascii "model name      : Intel(R) Xeon(TM) CPU 3.46GHz\n"
599 .ascii "stepping        : 4\n"
600 .ascii "cpu MHz         : 3200.000\n"
601 .ascii "cache size      : 2048 KB\n"
602 .ascii "physical id     : 1\n"
603 .ascii "siblings        : 2\n"
604 .ascii "core id         : 0\n"
605 .ascii "cpu cores       : 2\n"
606 .ascii "apicid          : 4\n"
607 .ascii "initial apicid  : 4\n"
608 .ascii "fpu             : yes\n"
609 .ascii "fpu_exception   : yes\n"
610 .ascii "cpuid level     : 6\n"
611 .ascii "wp              : yes\n"
612 .ascii "flags           : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc pebs bts pni dtes64 monitor ds_cpl vmx est cid cx16 xtpr pdcm lahf_lm tpr_shadow\n"
613 .ascii "bogomips        : 6934.13\n"
614 .ascii "clflush size    : 64\n"
615 .ascii "cache_alignment : 128\n"
616 .ascii "address sizes   : 36 bits physical, 48 bits virtual\n"
617 .ascii "power management:\n\0"
619 uname_info:
620 .ascii "Linux\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
621 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
623 .ascii "domori\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
624 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
626 .ascii "2.6.29\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
627 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
629 .ascii "#1 SMP Mon May 4 09:51:54 EDT 2009\0\0"
630 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
632 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
633 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
635 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
636 .ascii "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"
638 sysinfo_buff:
639 .long 0,0,0,0,0,0,0,0,2048*1024*1024,0,0,0,0,0,0,0
642 #============================================================================
643 #       section .bss
644 #============================================================================
645 .bss
647 .lcomm  text_buf, (N+F-1)
648 .lcomm  out_buffer,16384