* ~102 = 10011001
* (~102)+1 = 10011010 = 0x9A */
mov $0x9a9a9a9a9a9a9a9a, %rax
- movq %rax, %xmm15
- movddup %xmm15, %xmm8
+ movq %rax, %xmm8
+ punpcklbw %xmm8, %xmm8
//init %xmm9 mit "'a'-'A'= 97-65 = 32 = 0x20
mov $0x2020202020202020, %rax
- movq %rax, %xmm15
- movddup %xmm15, %xmm9
-
- //speicheradresse des pointers zeigt auf 16*8 feld = 128bit
- movdqu (%rdi, %rdx, 8), %xmm11
- movdqu (%rdi, %rdx, 8), %xmm12
+ movq %rax, %xmm9
+ punpcklbw %xmm9, %xmm9
/*addiere in %xmm11 "min_t-'A'"
* = -128 - 65 = 63 = 0x3f */
mov $0x3f3f3f3f3f3f3f3f, %rax
- movq %rax, %xmm15
- movddup %xmm15, %xmm10
+ movq %rax, %xmm10
+ punpcklbw %xmm10, %xmm10
.nextround:
//speicheradresse des pointers zeigt auf 16*8 feld = 128bit
* ist mit 'groesser' vertauscht und vice versa */
pcmpgtb %xmm11, %xmm15
+.differenz:
//Y = min(X, 'a' - 'A')
pminub %xmm9, %xmm15
//retuniere an die richtige speicheradresse
movapd %xmm12, (%rdi, %rdx, 8)
- //ist ein byte groesser als 0? dann steht 0xff drin
+ //entspricht ein byte dem nullbyte dann steht an jener stelle 0xff sonst 0x00
pcmpeqb %xmm14, %xmm12
//hol die MSBs aller bytes raus
pmovmskb %xmm12, %ecx
//ist %ecx gleich null? dann die naechsten 16byte bitte
jecxz .nextround
+ //speicheradresse des parameters zurueckgeben (wird noch modifziert)
mov %rdi, %rax
+
+ /*===============
+ * ab hier uebler hax um nach \0 trotzdem die gleichen bytes wie
+ * input zu haben, also um selbiges verhalten wie asmb_ref zu erzwingen */
+
+ //\0 byte stelle durch rausfinden des MSB des %ecx
+ bsf %ecx, %r11d
+
+ //das ergebnis zweimal abspeichern
+ mov %r11d, %ecx
+
+ //hint: in %xmm15 ist differenz gespeichert (vgl .differenz)
+
+ //leider shiften nur mit immediate! :(
+ cmp $8, %r11d
+ jc .rechtsshift1
+ psrldq $8, %xmm15
+ sub $8, %r11d
+
+.rechtsshift1:
+ cmp $4, %r11d
+ jc .rechtsshift2
+ psrldq $4, %xmm15
+ sub $4, %r11d
+
+.rechtsshift2:
+ cmp $2, %r11d
+ jc .rechtsshift3
+ psrldq $2, %xmm15
+ sub $2, %r11d
+
+.rechtsshift3:
+ cmp $1, %r11d
+ jc .linksshift
+ psrldq $1, %xmm15
+ sub $1, %r11d
+#==================
+.linksshift:
+ cmp $8, %ecx
+ jc .linksshift1
+ pslldq $8, %xmm15
+ sub $8, %ecx
+
+.linksshift1:
+ cmp $4, %ecx
+ jc .linksshift2
+ pslldq $4, %xmm15
+ sub $4, %ecx
+
+.linksshift2:
+ cmp $2, %ecx
+ jc .linksshift3
+ pslldq $2, %xmm15
+ sub $2, %ecx
+
+.linksshift3:
+ cmp $1, %ecx
+ jc .endshift
+ pslldq $1, %xmm15
+ sub $1, %ecx
+
+.endshift:
+ //betreffende speicherstelle in %xmm11 laden
+ movdqu -16(%rax, %rdx, 8), %xmm11
+ //und overhead wieder subtrahieren
+ psubb %xmm15, %xmm11
+
+ //ergebnis zurueckspielen und fertig \o/
+ movapd %xmm11, -16(%rax, %rdx, 8)
+
ret
.LFE2:
.size asmb, .-asmb