asmb: asmb verhaelt sich nun exakt wie asmb_ref
[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         cmp $8, %r11d
85         jc .rechtsshift1
86         psrldq $8, %xmm15
87         sub $8, %r11d
88
89 .rechtsshift1:
90         cmp $4, %r11d
91         jc .rechtsshift2
92         psrldq $4, %xmm15
93         sub $4, %r11d
94
95 .rechtsshift2:
96         cmp $2, %r11d
97         jc .rechtsshift3
98         psrldq $2, %xmm15
99         sub $2, %r11d
100
101 .rechtsshift3:
102         cmp $1, %r11d
103         jc .linksshift
104         psrldq $1, %xmm15
105         sub $1, %r11d
106 #==================
107 .linksshift:
108         cmp $8, %ecx
109         jc .linksshift1
110         pslldq $8, %xmm15
111         sub $8, %ecx
112
113 .linksshift1:
114         cmp $4, %ecx
115         jc .linksshift2
116         pslldq $4, %xmm15
117         sub $4, %ecx
118
119 .linksshift2:
120         cmp $2, %ecx
121         jc .linksshift3
122         pslldq $2, %xmm15
123         sub $2, %ecx
124
125 .linksshift3:
126         cmp $1, %ecx
127         jc .endshift
128         pslldq $1, %xmm15
129         sub $1, %ecx
130
131 .endshift:
132         //betreffende speicherstelle in %xmm11 laden
133         movdqu -16(%rax, %rdx, 8), %xmm11
134         //und overhead wieder subtrahieren
135         psubb %xmm15, %xmm11
136
137         //ergebnis zurueckspielen und fertig \o/
138         movapd %xmm11, -16(%rax, %rdx, 8)
139
140         ret
141 .LFE2:
142         .size   asmb, .-asmb
143         .section        .eh_frame,"a",@progbits
144 .Lframe1:
145         .long   .LECIE1-.LSCIE1
146 .LSCIE1:
147         .long   0x0
148         .byte   0x1
149         .string "zR"
150         .uleb128 0x1
151         .sleb128 -8
152         .byte   0x10
153         .uleb128 0x1
154         .byte   0x3
155         .byte   0xc
156         .uleb128 0x7
157         .uleb128 0x8
158         .byte   0x90
159         .uleb128 0x1
160         .align 8
161 .LECIE1:
162 .LSFDE1:
163         .long   .LEFDE1-.LASFDE1
164 .LASFDE1:
165         .long   .LASFDE1-.Lframe1
166         .long   .LFB2
167         .long   .LFE2-.LFB2
168         .uleb128 0x0
169         .align 8
170 .LEFDE1:
171         .ident  "GCC: (Debian 4.3.2-1.1) 4.3.2"
172         .section        .note.GNU-stack,"",@progbits