Ja, aber ich habe mir den assembler output mal angesehen. Schneller ist es wohl doch mit Hilfvariable, da wir mit 8bit und nicht 32 bit arbeiten. Naja... macht aber keinen Unterschied da die Festplatte die Bremse ist. Habe auch eine MMX Routine und davon abgeleitet mit 32 bit int was geschrieben, nur macht keinen Sinn wegen I/O... Aber bei Interesse kann man ja dieses Code Fragment begutachten:
unsigned int im2 = 0x00FF00FF; unsigned int im1 = 0xFF00FF00; for (i = 4; i < to_read; i += 4) { unsigned int bin = *buffer; unsigned int b1 = bin << 8; unsigned int b2 = bin >> 8; b1 &= im1; b2 &= im2; *buffer = b1 | b2; buffer += 4; }
Mit etwas Geschick könnte man obiges auch auf 64 bit longs auf Athlon64 selbst-tunend machend, also daß der bei 32bit 2 Werte und bei 64bit 4 Werte "swapt". Damit wäre es auf 64bit Plattformen so gut wie MMX.
und dasselbe in MMX (bringt aber nix; scheint sogar langsamer, habe aber das malloc auch nicht auf 8byte aligned):
#if __GNUC__ < 4
typedef short v4hi __attribute__ ((__mode__(__V4HI__)));
typedef int v2si __attribute__ ((__mode__(__V2SI__)));
typedef int di __attribute__ ((__mode__(__DI__)));
#else
typedef short v4hi __attribute__ ((vector_size (8)));
typedef int v2si __attribute__ ((vector_size (8)));
typedef int di __attribute__ ((vector_size (8)));
#endif
#define ALIGN16(x) x __attribute__((aligned(16)))
union {
unsigned short s[4];
v4hi v;
} ALIGN16(m2) = {{0x00FF, 0x00FF, 0x00FF, 0x00FF}};
union {
unsigned short s[4];
v4hi v;
} ALIGN16(m1) = {{0xFF00, 0xFF00, 0xFF00, 0xFF00}};
for (i = 8; i < to_read; i += 8) {
v4hi v1, v2;
v4hi vin;
vin = *(v4hi*)buffer;
v1 = __builtin_ia32_psllw(vin, 8);
v2 = __builtin_ia32_psrlw(vin, 8);
v1 = __builtin_ia32_pand(v1, m1.v);
v2 = __builtin_ia32_pand(v2, m2.v);
*(di*)buffer = __builtin_ia32_por(v1, v2);
buffer += 8;
}
__builtin_ia32_emms();
Alles anzeigen
Alles wie gesagt GPL, der "Prolog" zum MMX Fragment ist auch in LGPL verfügbar (siehe OpenAL).