zeckensack
2002-08-25, 08:52:53
Scheint ja höllisch kompliziert zu sein ... allgemeine Empfehlung bis jetzt, war einfach den NASM zu nehmen, damit libs zu erzeugen und dazuzubinden.
Das schmeckt mir aus mehreren Gründen nicht:
1a)Ich will mich nicht mit calling conventions rumärgern, das Projekt ist schon unübersichtlich genug
1b)Ich hätte das ganze gerne typsicher
2)Ich hätte gerne den C-Präprozessor davor, um MMX und MMX+MOVNTQ-Code aus dem gleichen Source erzeugen zu können
3)Ich nutze C++ Namespaces
Auf 'richtige' ASM-Funktionen kann ich ganz gut verzichten.
Ich habe im Moment 45kByte (!!) Quellcode mit Funktionen, die größtenteils aus Inline-Assembler bestehen. Der lässt sich in der aktuellen Form allerdings nur unter VC vernünftig kompilieren.
Was ich gerne hätte, wäre zumindest erstmal eine vernünftige Anleitung zum Inline-Assembler (GCC-Manpages geben nichts her), um selber Hand anlegen zu können.
Am allerbesten gleich ein fertiges Tool, das automatisch konvertieren kann :)
Das sieht bei mir zB so aus:Irgendwo im C++-Code ...
#define STOREQWORD MOVQ
#define END_STORE //warning killer
namespace MMX
{
#include "cc_texture_stuff.i"
....
}
#undef STOREQWORD
#undef END_STORE
#define STOREQWORD MOVNTQ
#define END_STORE SFENCE
namespace eMMX
{
#include "cc_texture_stuff.i"
....
}
cc_texture_stuff.i
void
decode_paletted_rgb(void* const target,const void*const source,const void*const palette,uint pixels)
{
if (pixels==0) return;
__asm
{
PUSH EBP
MOVQ mm7,c4_8888 //we set alpha to full for all output pixels
MOV ESI,source
MOV EDI,target
MOV ECX,pixels
MOV EBX,ECX
MOV EBP,palette //warning: local vars are gone now!
AND ECX,0xFFFFFFF8 //decode eight pixels per iteration
JZ pre_loop_1
ADD ESI,ECX //input is one byte per pixel
LEA EDI,[EDI+4*ECX] //output is four bytes per pixel
SHR ECX,1
NEG ECX
loop_8:
MOV EDX,[ESI+2*ECX]
MOVZX EAX,DL
MOVD mm0,[EBP+4*EAX]
MOVZX EAX,DH
PUNPCKLDQ mm0,[EBP+4*EAX]
SHR EDX,16
MOVZX EAX,DL
MOVD mm1,[EBP+4*EAX]
MOVZX EAX,DH
PUNPCKLDQ mm1,[EBP+4*EAX]
POR mm0,mm7
POR mm1,mm7
MOV EDX,[ESI+2*ECX+4]
MOVZX EAX,DL
MOVD mm2,[EBP+4*EAX]
MOVZX EAX,DH
PUNPCKLDQ mm2,[EBP+4*EAX]
SHR EDX,16
MOVZX EAX,DL
MOVD mm3,[EBP+4*EAX]
MOVZX EAX,DH
PUNPCKLDQ mm3,[EBP+4*EAX]
POR mm2,mm7
POR mm3,mm7
STOREQWORD [EDI+8*ECX],mm0
STOREQWORD [EDI+8*ECX+8],mm1
STOREQWORD [EDI+8*ECX+16],mm2
STOREQWORD [EDI+8*ECX+24],mm3
ADD ECX,4
JNZ loop_8
pre_loop_1:
AND EBX,7
JZ finished
ADD ESI,EBX
LEA EDI,[EDI+4*EBX]
NEG EBX
MOVD EDX,mm7
loop_1:
MOVZX EAX,BYTE PTR [ESI+EBX]
MOV ECX,[EBP+4*EAX]
OR ECX,EDX
MOV [EDI+4*EBX],ECX
INC EBX
JNZ loop_1
finished:
END_STORE
EMMS
POP EBP
}
}
Brauche also folgendes:
Zugriff auf die Funktionsparameter (definiert mittels ordentlicher C-Prototypen)
Maximal ein C-Statement pro Funktion
Und dann haufenweise ASM (genaue Syntax in GCC ???)
Und wie gesagt, von der Sorte habe ich reichlich, wäre also am schönsten, das irgendwie automatisieren zu können, ich will nämlich weg von VC, weit weit weg =)
Das schmeckt mir aus mehreren Gründen nicht:
1a)Ich will mich nicht mit calling conventions rumärgern, das Projekt ist schon unübersichtlich genug
1b)Ich hätte das ganze gerne typsicher
2)Ich hätte gerne den C-Präprozessor davor, um MMX und MMX+MOVNTQ-Code aus dem gleichen Source erzeugen zu können
3)Ich nutze C++ Namespaces
Auf 'richtige' ASM-Funktionen kann ich ganz gut verzichten.
Ich habe im Moment 45kByte (!!) Quellcode mit Funktionen, die größtenteils aus Inline-Assembler bestehen. Der lässt sich in der aktuellen Form allerdings nur unter VC vernünftig kompilieren.
Was ich gerne hätte, wäre zumindest erstmal eine vernünftige Anleitung zum Inline-Assembler (GCC-Manpages geben nichts her), um selber Hand anlegen zu können.
Am allerbesten gleich ein fertiges Tool, das automatisch konvertieren kann :)
Das sieht bei mir zB so aus:Irgendwo im C++-Code ...
#define STOREQWORD MOVQ
#define END_STORE //warning killer
namespace MMX
{
#include "cc_texture_stuff.i"
....
}
#undef STOREQWORD
#undef END_STORE
#define STOREQWORD MOVNTQ
#define END_STORE SFENCE
namespace eMMX
{
#include "cc_texture_stuff.i"
....
}
cc_texture_stuff.i
void
decode_paletted_rgb(void* const target,const void*const source,const void*const palette,uint pixels)
{
if (pixels==0) return;
__asm
{
PUSH EBP
MOVQ mm7,c4_8888 //we set alpha to full for all output pixels
MOV ESI,source
MOV EDI,target
MOV ECX,pixels
MOV EBX,ECX
MOV EBP,palette //warning: local vars are gone now!
AND ECX,0xFFFFFFF8 //decode eight pixels per iteration
JZ pre_loop_1
ADD ESI,ECX //input is one byte per pixel
LEA EDI,[EDI+4*ECX] //output is four bytes per pixel
SHR ECX,1
NEG ECX
loop_8:
MOV EDX,[ESI+2*ECX]
MOVZX EAX,DL
MOVD mm0,[EBP+4*EAX]
MOVZX EAX,DH
PUNPCKLDQ mm0,[EBP+4*EAX]
SHR EDX,16
MOVZX EAX,DL
MOVD mm1,[EBP+4*EAX]
MOVZX EAX,DH
PUNPCKLDQ mm1,[EBP+4*EAX]
POR mm0,mm7
POR mm1,mm7
MOV EDX,[ESI+2*ECX+4]
MOVZX EAX,DL
MOVD mm2,[EBP+4*EAX]
MOVZX EAX,DH
PUNPCKLDQ mm2,[EBP+4*EAX]
SHR EDX,16
MOVZX EAX,DL
MOVD mm3,[EBP+4*EAX]
MOVZX EAX,DH
PUNPCKLDQ mm3,[EBP+4*EAX]
POR mm2,mm7
POR mm3,mm7
STOREQWORD [EDI+8*ECX],mm0
STOREQWORD [EDI+8*ECX+8],mm1
STOREQWORD [EDI+8*ECX+16],mm2
STOREQWORD [EDI+8*ECX+24],mm3
ADD ECX,4
JNZ loop_8
pre_loop_1:
AND EBX,7
JZ finished
ADD ESI,EBX
LEA EDI,[EDI+4*EBX]
NEG EBX
MOVD EDX,mm7
loop_1:
MOVZX EAX,BYTE PTR [ESI+EBX]
MOV ECX,[EBP+4*EAX]
OR ECX,EDX
MOV [EDI+4*EBX],ECX
INC EBX
JNZ loop_1
finished:
END_STORE
EMMS
POP EBP
}
}
Brauche also folgendes:
Zugriff auf die Funktionsparameter (definiert mittels ordentlicher C-Prototypen)
Maximal ein C-Statement pro Funktion
Und dann haufenweise ASM (genaue Syntax in GCC ???)
Und wie gesagt, von der Sorte habe ich reichlich, wäre also am schönsten, das irgendwie automatisieren zu können, ich will nämlich weg von VC, weit weit weg =)