asmb: hint von martin perner (btr statt cmp/sub) und gistupdate von ihm
[uebersetzerbau-ss10.git] / asmb / asmb.s
1         .file   "asmb.c"
2         .text
3 .globl asmb
4         .type   asmb, @function
5 asmb:
6 .LFB2:
7         xor %rdx, %rdx
8
9         //soll einfach null sein
10         pxor %xmm14, %xmm14
11
12         /*init %xmm8 mit "'Z' + 1 + min_t - 'A'" fuer jedes byte
13         * 'Z' + 1 + min_t - 'A' = 90 + 1 - 128 - 65 = -102
14         * 102 = 01100110
15         * ~102 = 10011001
16         * (~102)+1 = 10011010 = 0x9A */
17         mov $0x9a9a9a9a9a9a9a9a, %rax
18         movq %rax, %xmm8
19         punpcklbw %xmm8, %xmm8
20
21         //init %xmm9 mit "'a'-'A'= 97-65 = 32 = 0x20
22         mov $0x2020202020202020, %rax
23         movq %rax, %xmm9
24         punpcklbw %xmm9, %xmm9
25
26         /*addiere in %xmm11 "min_t-'A'"
27         * = -128 - 65 = 63 = 0x3f */
28         mov $0x3f3f3f3f3f3f3f3f, %rax
29         movq %rax, %xmm10
30         punpcklbw %xmm10, %xmm10
31
32 .nextround:
33         //speicheradresse des pointers zeigt auf 16*8 feld = 128bit
34         movdqu (%rdi, %rdx, 8), %xmm11
35         movdqu (%rdi, %rdx, 8), %xmm12
36
37         //c+min_t-'A'
38         paddb %xmm10, %xmm11
39
40         //0x9a9a... zwischenspeichern
41         movdqa %xmm8, %xmm15
42
43         /*"Packed COMpare Greater Than (Byte)"
44         * X = 'Z' + 1 + min_t - 'A' > c + min_t - 'A' ? 0xff : 0
45         * achtung beim intuitiven lesen des befehles. 'kleiner' 
46         * ist mit 'groesser' vertauscht und vice versa */
47         pcmpgtb %xmm11, %xmm15
48
49 .differenz:
50         //Y = min(X, 'a' - 'A')
51         pminub %xmm9, %xmm15
52
53         //c += Y
54         paddb %xmm15, %xmm12
55
56         //retuniere an die richtige speicheradresse
57         movapd %xmm12, (%rdi, %rdx, 8)
58
59         //entspricht ein byte dem nullbyte dann steht an jener stelle 0xff sonst 0x00
60         pcmpeqb %xmm14, %xmm12
61         //hol die MSBs aller bytes raus
62         pmovmskb %xmm12, %ecx
63         add $2, %rdx
64
65         //ist %ecx gleich null? dann die naechsten 16byte bitte
66         jecxz .nextround
67
68         //speicheradresse des parameters zurueckgeben (wird noch modifziert)
69         mov %rdi, %rax
70
71         /*===============
72         * ab hier uebler hax um nach \0 trotzdem die gleichen bytes wie
73         * input zu haben, also um selbiges verhalten wie asmb_ref zu erzwingen */
74
75         //\0 byte stelle durch rausfinden des MSB des %ecx
76         bsf %ecx, %r11d
77
78         //das ergebnis zweimal abspeichern
79         mov %r11d, %ecx
80
81         //hint: in %xmm15 ist differenz gespeichert (vgl .differenz)
82
83         //leider shiften nur mit immediate! :(
84         btr $3, %r11d
85         jnc .rechtsshift1
86         psrldq $8, %xmm15
87
88 .rechtsshift1:
89         btr $2, %r11d
90         jnc .rechtsshift2
91         psrldq $4, %xmm15
92
93 .rechtsshift2:
94         btr $1, %r11d
95         jnc .rechtsshift3
96         psrldq $2, %xmm15
97
98 .rechtsshift3:
99         btr $0, %r11d
100         jnc .linksshift
101         psrldq $1, %xmm15
102 #==================
103 .linksshift:
104         btr $3, %ecx
105         jnc .linksshift1
106         pslldq $8, %xmm15
107
108 .linksshift1:
109         btr $2, %ecx
110         jnc .linksshift2
111         pslldq $4, %xmm15
112
113 .linksshift2:
114         btr $1, %ecx
115         jnc .linksshift3
116         pslldq $2, %xmm15
117
118 .linksshift3:
119         btr $0, %ecx
120         jnc .endshift
121         pslldq $1, %xmm15
122
123 .endshift:
124         //betreffende speicherstelle in %xmm11 laden
125         movdqu -16(%rax, %rdx, 8), %xmm11
126         //und overhead wieder subtrahieren
127         psubb %xmm15, %xmm11
128
129         //ergebnis zurueckspielen und fertig \o/
130         movapd %xmm11, -16(%rax, %rdx, 8)
131
132         ret
133 .LFE2:
134         .size   asmb, .-asmb
135         .section        .eh_frame,"a",@progbits
136 .Lframe1:
137         .long   .LECIE1-.LSCIE1
138 .LSCIE1:
139         .long   0x0
140         .byte   0x1
141         .string "zR"
142         .uleb128 0x1
143         .sleb128 -8
144         .byte   0x10
145         .uleb128 0x1
146         .byte   0x3
147         .byte   0xc
148         .uleb128 0x7
149         .uleb128 0x8
150         .byte   0x90
151         .uleb128 0x1
152         .align 8
153 .LECIE1:
154 .LSFDE1:
155         .long   .LEFDE1-.LASFDE1
156 .LASFDE1:
157         .long   .LASFDE1-.Lframe1
158         .long   .LFB2
159         .long   .LFE2-.LFB2
160         .uleb128 0x0
161         .align 8
162 .LEFDE1:
163         .ident  "GCC: (Debian 4.3.2-1.1) 4.3.2"
164         .section        .note.GNU-stack,"",@progbits