Discussion:
Rotation in einem Register
(zu alt für eine Antwort)
Hipo
2006-05-23 12:16:08 UTC
Permalink
Hi.
Ich hab noch ein Problem, auf dessen Lösung ich einfachnicht komme.
Ich habe 8 Bytes in einem Register, z.B. RAX. Sie sind wie folgt
angeordnet:

|a b c d e f g h|

Mein Ziel ist es, das Register am Schluss so ausehen zu lassen:

|c d a b g h e f|

Ich muss also die hohen und die niedrigen Byte voneinander unabhängig
rotieren.
Meine Lösung wäre:

ROTL EAX, 16
ROTL RAX, 32
ROTL EAX, 16
ROTL RAX, 32

Ich finde das nicht elegant, und sicherlich nicht sher effizient, da ich
diese Berechnung sehr oft durchlaufen muss.

Hat vielleicht jemand einen Trick auf Lager, der diese Operation
effizienter erledigen kann?

mfg, Hipo
Sebastian Biallas
2006-05-23 13:41:13 UTC
Permalink
Post by Hipo
Hi.
Ich hab noch ein Problem, auf dessen Lösung ich einfachnicht komme.
Ich habe 8 Bytes in einem Register, z.B. RAX. Sie sind wie folgt
|a b c d e f g h|
|c d a b g h e f|
Ich muss also die hohen und die niedrigen Byte voneinander unabhängig
rotieren.
ROTL EAX, 16
Das löscht den oberen Teil von RAX. Hast Du das überhaupt ausprobiert?
Post by Hipo
Hat vielleicht jemand einen Trick auf Lager, der diese Operation
effizienter erledigen kann?
pshufw

Ansonsten würde ich den Wert in EDX:EAX speichern. Was versuchst Du da
eigentlich zu erreichen?
--
Gruß,
Sebastian
Hipo
2006-05-23 13:56:20 UTC
Permalink
Post by Sebastian Biallas
Post by Hipo
Hi.
Ich hab noch ein Problem, auf dessen Lösung ich einfachnicht komme.
Ich habe 8 Bytes in einem Register, z.B. RAX. Sie sind wie folgt
|a b c d e f g h|
|c d a b g h e f|
Ich muss also die hohen und die niedrigen Byte voneinander unabhängig
rotieren.
ROTL EAX, 16
Das löscht den oberen Teil von RAX. Hast Du das überhaupt ausprobiert?
Ich bin noch in der Planungsphase. Ich hätte es gern ausprobiert, aber
VS 2005 für x64 unterstützt keinen inline assembler. Bisher hatte ich
noch keine Zeit reinen Assembler code zu schreiben, wobei ich mich da
erst einlesen muss, da ich es noch nicht verwerendet hab.
Post by Sebastian Biallas
Post by Hipo
Hat vielleicht jemand einen Trick auf Lager, der diese Operation
effizienter erledigen kann?
pshufw
Kannst du mir aus Erfahrung sagen, wie sehr die Performance unter
Datentransfers zwischen XMM und GPR Register leidet. Ich habe
diesbezüglich bereits einige Warnungen erhalten.
Post by Sebastian Biallas
Ansonsten würde ich den Wert in EDX:EAX speichern. Was versuchst Du da
eigentlich zu erreichen?
Für einen Teil eines Verschlüsselungsalgorithmus muss ich oben
beschriebene Permutationen durchführen.

mfg, Hipo
Sebastian Biallas
2006-05-23 14:11:49 UTC
Permalink
Post by Hipo
Post by Sebastian Biallas
pshufw
Kannst du mir aus Erfahrung sagen, wie sehr die Performance unter
Datentransfers zwischen XMM und GPR Register leidet. Ich habe
diesbezüglich bereits einige Warnungen erhalten.
Wahrscheinlich zu recht. Besser ist es, alles mit MMX/SSE zu machen.
--
Gruß,
Sebastian
Jan Bruns
2006-05-24 00:27:15 UTC
Permalink
Post by Sebastian Biallas
Post by Hipo
ROTL EAX, 16
Das löscht den oberen Teil von RAX. Hast Du das überhaupt ausprobiert?
Wie heisst denn in dieser neumodischen 64-Bit Technik der Befehl
für Rotation? Gab doch schon immer rot und shift, mit und ohne Carry.

Grussauch
Sebastian Biallas
2006-05-24 00:58:20 UTC
Permalink
Post by Jan Bruns
Post by Sebastian Biallas
Post by Hipo
ROTL EAX, 16
Das löscht den oberen Teil von RAX. Hast Du das überhaupt ausprobiert?
Wie heisst denn in dieser neumodischen 64-Bit Technik der Befehl
für Rotation?
Weiterhin rol bzw. ror usw, das da oben ist wahrscheinlich ein
Tippfehler. Es hat sich von 32->64 am Befehlssatz eigentlich kaum was
geändert. Ein paar Befehle sind rausgeflogen, hinzu kam eigentlich nur
movsxd, ein neuer Adressierungsmodus (IP-relativ), ein bissl SSE-Kram
und esoterisches. Und man hat halt doppelt so viele Register.

Man sollte halt nur wissen, dass beim Zugriff auf ein Teilregister immer
die oberen 32 Bit gelöscht werden.

Die Aufgabe des OP ist für ein 64 Bit Register wohl nicht so einfach,
deshalb mein Vorschlag, auf zwei 32 Bit Register auszuweichen.
--
Gruß,
Sebastian
Jan Bruns
2006-05-24 01:22:49 UTC
Permalink
Post by Sebastian Biallas
Man sollte halt nur wissen, dass beim Zugriff auf ein Teilregister immer
die oberen 32 Bit gelöscht werden.
Das muss ich bei Gelegenheit mal nachschlagen...

Ist ja bisher auch anders gewesen:

mov eax,$12345678
mov ax, $5678
mov al, $78

-> eax = $12345678
Sebastian Biallas
2006-05-24 09:55:02 UTC
Permalink
Post by Jan Bruns
Post by Sebastian Biallas
Man sollte halt nur wissen, dass beim Zugriff auf ein Teilregister immer
die oberen 32 Bit gelöscht werden.
Das muss ich bei Gelegenheit mal nachschlagen...
mov eax,$12345678
mov ax, $5678
mov al, $78
-> eax = $12345678
Das gilt auch weiterhin. Allerdings gilt danach (rax&0xffffffff00000000)==0.

Das ist aber auch sinnvoll so. Obiges Verhalten war vor 20 Jahren
vielleicht noch verständlich, ist aber für heutige Prozessoren sehr
schlecht, weil man mit den partial register stalls umgehen muss.

Bei dem "mov al, $78" muss der Prozessor entweder auf den Wert von rax
warten, bis er den Befehl zuende ausführen kann, oder er zerteilt das
Register und muss es später u.U. wieder kompliziert zusammenführen. Ein
"mov eax, $78" hingegen kann er unabhängig von dem vorigen Wert von rax
ausführen.

Schau Dir mal Code vom einem aktuellen Compiler an, der mit Bytes
handtiert (z.B. Stringverarbeitung). Der ist voll von scheinbar
unnötigen movzx/movsx. Das macht man halt, um dem Prozessor Arbeit
abzunehmen.
--
Gruß,
Sebastian
Jan Bruns
2006-05-24 16:27:37 UTC
Permalink
Post by Sebastian Biallas
Post by Jan Bruns
mov eax,$12345678
mov ax, $5678
mov al, $78
-> eax = $12345678
Das gilt auch weiterhin. Allerdings gilt danach (rax&0xffffffff00000000)==0.
Naja, interessiert mich momentan nicht hinreichend, um das nachzuschlagen.
Jedenfalls: Ziemlich inkonsequent sieht das aus.
Post by Sebastian Biallas
Das ist aber auch sinnvoll so. Obiges Verhalten war vor 20 Jahren
vielleicht noch verständlich, ist aber für heutige Prozessoren sehr
schlecht, weil man mit den partial register stalls umgehen muss.
Also ich kann nun nicht gerade behaupten, über die pipelinetechnsichen
Hintergründe bzgl. partieller Register genauestens informiert zu sein.
Klingt für mich eigentlich eher nach Integrationsdichte, als nach
echten Engpässen.
Post by Sebastian Biallas
Bei dem "mov al, $78" muss der Prozessor entweder auf den Wert von rax
warten, bis er den Befehl zuende ausführen kann, oder er zerteilt das
Register und muss es später u.U. wieder kompliziert zusammenführen. Ein
"mov eax, $78" hingegen kann er unabhängig von dem vorigen Wert von rax
ausführen.
Der Prozessor muss auf rax warten? Wo ist denn rax implementiert?

Du meinst wahrscheinlich einfach irgendeine zentrale Verarbeitungseinheit
in der CPU. Dazu ist einfach mal festzustellen, daß es neben schematischen
Trennung von Befehlausführung und Registersatz auch völlig andere
Implementationen denkbar sind. Bspw. könnte man für jedes Register
eine eigene Ausführungseinheit vorsehen, um dann nur noch Datentransfers
zwischen Registern bzw. externem Speicher zentralisiert organisieren zu
müssen. In Anbetracht der "aktuellen" Problematik weiterhin schnell
steigende(r) Integrationsumfang/dichte bei geringem Taktratenzuwachs
vielleicht nichtmal eine völlig absurde Vorgehensweise.
Post by Sebastian Biallas
Schau Dir mal Code vom einem aktuellen Compiler an, der mit Bytes
handtiert (z.B. Stringverarbeitung). Der ist voll von scheinbar
unnötigen movzx/movsx. Das macht man halt, um dem Prozessor Arbeit
abzunehmen.
Also Du meinst den Zusammenhang, daß obwohl nur bspw. vereinzelte
Bytes zu verarbeiten sind (von denen mehrere in einem Register
gespeichert werden könnten), in der Praxis trotzdem regelmässig nur
eine Dateneinheit pro Register verwendet wird, und dabei denn auch
unnötig häufig die nicht verwendeten Anteile explizit überschrieben
werden?

Das hat vielleicht verschiedene Ursachen, aber einer davon ist
sicherlich memory alignment. Wenn es dagegen darum geht, bspw.
den Befehl "mov al,bl" CPU-optimiert zu schreiben, kam da
bislang regelmässig sowas wie "mov eax,ebx" heraus, wenn die
oberen Anteile von ebx eh' trivial sind, obwohl die Formulierung
"movzx eax,bl" sicherlich einfacher ist.

Gruss

Jan Bruns
Sebastian Biallas
2006-05-24 17:01:12 UTC
Permalink
Post by Jan Bruns
Post by Sebastian Biallas
Post by Jan Bruns
mov eax,$12345678
mov ax, $5678
mov al, $78
-> eax = $12345678
Das gilt auch weiterhin. Allerdings gilt danach (rax&0xffffffff00000000)==0.
Naja, interessiert mich momentan nicht hinreichend, um das nachzuschlagen.
Jedenfalls: Ziemlich inkonsequent sieht das aus.
Es war aber nötig, ansonsten hätte man immer mit den 64 Bit Registern
arbeiten müssen, wenn man den Code nicht unnötig verlangsamen möchte.
Post by Jan Bruns
Post by Sebastian Biallas
Das ist aber auch sinnvoll so. Obiges Verhalten war vor 20 Jahren
vielleicht noch verständlich, ist aber für heutige Prozessoren sehr
schlecht, weil man mit den partial register stalls umgehen muss.
Also ich kann nun nicht gerade behaupten, über die pipelinetechnsichen
Hintergründe bzgl. partieller Register genauestens informiert zu sein.
Klingt für mich eigentlich eher nach Integrationsdichte, als nach
echten Engpässen.
Ich weiß nicht, was Du mit Integrationsdichte meinst.
Post by Jan Bruns
Post by Sebastian Biallas
Bei dem "mov al, $78" muss der Prozessor entweder auf den Wert von rax
warten, bis er den Befehl zuende ausführen kann, oder er zerteilt das
Register und muss es später u.U. wieder kompliziert zusammenführen. Ein
"mov eax, $78" hingegen kann er unabhängig von dem vorigen Wert von rax
ausführen.
Der Prozessor muss auf rax warten? Wo ist denn rax implementiert?
Der Prozessor hat vielleicht 64 Register von denen mehrere den Wert von
rax zu einem bestimmten Zeitpunkt enthalten können. Nehmen wir z.B. so
einen Code:

mov eax, 1
push eax
mov eax, 2
push eax

Der Prozessor kann hier die beiden movs parallel ausführen (in
verschiende interne Register), da sie von nichts abhängen.

Würde jedoch "mov eax, 1" den oberen Teil von rax erhalten, dann gibt es
zwei Möglichkeiten:

1) Der "mov eax, 2" wird erst ausgeführt, wenn der finale Wert von rax
bekannt ist (dh. bis alle Anweisungen davor, die rax anfassen,
bearbeitet sind).
2) Der Prozessor teilt rax auf verschiedene interne Register auf. Falls
danach rax gelesen wird, muss der Prozessor die internen Register wieder
zusammenfassen.

Beides ist nicht schön.
Post by Jan Bruns
Du meinst wahrscheinlich einfach irgendeine zentrale Verarbeitungseinheit
in der CPU. Dazu ist einfach mal festzustellen, daß es neben schematischen
Trennung von Befehlausführung und Registersatz auch völlig andere
Implementationen denkbar sind. Bspw. könnte man für jedes Register
eine eigene Ausführungseinheit vorsehen, um dann nur noch Datentransfers
zwischen Registern bzw. externem Speicher zentralisiert organisieren zu
müssen. In Anbetracht der "aktuellen" Problematik weiterhin schnell
steigende(r) Integrationsumfang/dichte bei geringem Taktratenzuwachs
vielleicht nichtmal eine völlig absurde Vorgehensweise.
Ich bin kein Prozessorhersteller, und ich kann nur die momentane
Situation reflektieren.
Post by Jan Bruns
Post by Sebastian Biallas
Schau Dir mal Code vom einem aktuellen Compiler an, der mit Bytes
handtiert (z.B. Stringverarbeitung). Der ist voll von scheinbar
unnötigen movzx/movsx. Das macht man halt, um dem Prozessor Arbeit
abzunehmen.
Also Du meinst den Zusammenhang, daß obwohl nur bspw. vereinzelte
Bytes zu verarbeiten sind (von denen mehrere in einem Register
gespeichert werden könnten), in der Praxis trotzdem regelmässig nur
eine Dateneinheit pro Register verwendet wird, und dabei denn auch
unnötig häufig die nicht verwendeten Anteile explizit überschrieben
werden?
Nein. Dass ah usw. nicht mehr verwendet werden, hat zwar ähnliche
Ursachen, aber das meine ich nicht.

Ich meine z.B. sowas:

movzx eax, [byte1]
movzx ecx, [byte2]
cmp eax, ecx

statt:

mov al, [byte1]
mov cl, [byte2]
cmp al, cl

Ein "movzx eax, .." kann unabhängig davon ausgeführt werden, was in eax
steht. Bei "mov al, .." haben wir die Situation, die ich oben
beschrieben habe.
Post by Jan Bruns
Das hat vielleicht verschiedene Ursachen, aber einer davon ist
sicherlich memory alignment.
Nein, das hat mit Alignment nichts zu tun. Byte-Zugriffe sind immer aligned.
--
Gruß,
Sebastian
Jan Bruns
2006-05-24 19:36:16 UTC
Permalink
Post by Sebastian Biallas
Post by Jan Bruns
Post by Sebastian Biallas
Post by Jan Bruns
mov eax,$12345678
mov ax, $5678
mov al, $78
-> eax = $12345678
Das gilt auch weiterhin. Allerdings gilt danach (rax&0xffffffff00000000)==0.
Naja, interessiert mich momentan nicht hinreichend, um das nachzuschlagen.
Jedenfalls: Ziemlich inkonsequent sieht das aus.
Es war aber nötig, ansonsten hätte man immer mit den 64 Bit Registern
arbeiten müssen, wenn man den Code nicht unnötig verlangsamen möchte.
Nee, komm, also Notwendigkeit ist wat anners.

Arbeitet man nicht ohnehin immer mit 64-Bit Registern?
Post by Sebastian Biallas
Post by Jan Bruns
Post by Sebastian Biallas
Das ist aber auch sinnvoll so. Obiges Verhalten war vor 20 Jahren
vielleicht noch verständlich, ist aber für heutige Prozessoren sehr
schlecht, weil man mit den partial register stalls umgehen muss.
Also ich kann nun nicht gerade behaupten, über die pipelinetechnsichen
Hintergründe bzgl. partieller Register genauestens informiert zu sein.
Klingt für mich eigentlich eher nach Integrationsdichte, als nach
echten Engpässen.
Ich weiß nicht, was Du mit Integrationsdichte meinst.
Damit habe ich die Transitoranzahl gemeint. Ist üblich.
Post by Sebastian Biallas
Post by Jan Bruns
Post by Sebastian Biallas
Bei dem "mov al, $78" muss der Prozessor entweder auf den Wert von rax
warten, bis er den Befehl zuende ausführen kann, oder er zerteilt das
Register und muss es später u.U. wieder kompliziert zusammenführen. Ein
"mov eax, $78" hingegen kann er unabhängig von dem vorigen Wert von rax
ausführen.
Der Prozessor muss auf rax warten? Wo ist denn rax implementiert?
Der Prozessor hat vielleicht 64 Register von denen mehrere den Wert von
rax zu einem bestimmten Zeitpunkt enthalten können. Nehmen wir z.B. so
[...]
Der Prozessor kann hier die beiden movs parallel ausführen (in
verschiende interne Register), da sie von nichts abhängen.
Würde jedoch "mov eax, 1" den oberen Teil von rax erhalten, dann gibt es
Hier hast Du nun erstmal die Möglichkeit vergessen, daß man dann doch
durchaus auch movzx schreiben könnte, um exakt die obige Situation
zu konstruieren.
Post by Sebastian Biallas
1) Der "mov eax, 2" wird erst ausgeführt, wenn der finale Wert von rax
bekannt ist (dh. bis alle Anweisungen davor, die rax anfassen,
bearbeitet sind).
2) Der Prozessor teilt rax auf verschiedene interne Register auf. Falls
danach rax gelesen wird, muss der Prozessor die internen Register wieder
zusammenfassen.
Beides ist nicht schön.
Naja, das hattest Du ja schon geschrieben. Ist ja auch nett, wenn Du
versuchst, die aktuellen Gegebenheiten zu beschreiben.
Post by Sebastian Biallas
Post by Jan Bruns
Du meinst wahrscheinlich einfach irgendeine zentrale Verarbeitungseinheit
in der CPU. Dazu ist einfach mal festzustellen, daß es neben schematischen
Trennung von Befehlausführung und Registersatz auch völlig andere
Implementationen denkbar sind. Bspw. könnte man für jedes Register
eine eigene Ausführungseinheit vorsehen, um dann nur noch Datentransfers
zwischen Registern bzw. externem Speicher zentralisiert organisieren zu
müssen. In Anbetracht der "aktuellen" Problematik weiterhin schnell
steigende(r) Integrationsumfang/dichte bei geringem Taktratenzuwachs
vielleicht nichtmal eine völlig absurde Vorgehensweise.
Ich bin kein Prozessorhersteller, und ich kann nur die momentane
Situation reflektieren.
So wie du hier argumentierst wäre es aber doch ganz sinnig, wenn Du
wenigstens bezüglich dieses Details (zentrales execute auf "externem"
Registerspeicher) irgendwelche Zukunftserwartungen hättest.

Worauf willst Du sonst die Begriffe "notwendig, logisch, sinnvoll"
stützen?
Post by Sebastian Biallas
Post by Jan Bruns
Das hat vielleicht verschiedene Ursachen, aber einer davon ist
sicherlich memory alignment.
Nein, das hat mit Alignment nichts zu tun. Byte-Zugriffe sind
immer aligned.
Sehe ich anders, is aber echt egal.

gruss

Jan Bruns
Sebastian Biallas
2006-05-25 21:25:04 UTC
Permalink
Post by Jan Bruns
Post by Sebastian Biallas
Es war aber nötig, ansonsten hätte man immer mit den 64 Bit Registern
arbeiten müssen, wenn man den Code nicht unnötig verlangsamen möchte.
Nee, komm, also Notwendigkeit ist wat anners.
Arbeitet man nicht ohnehin immer mit 64-Bit Registern?
Da ein int üblicherweise noch 32 Bit groß ist, arbeitet man häufig noch
mit 32 Bit Registern.
Post by Jan Bruns
Post by Sebastian Biallas
Post by Jan Bruns
Also ich kann nun nicht gerade behaupten, über die pipelinetechnsichen
Hintergründe bzgl. partieller Register genauestens informiert zu sein.
Klingt für mich eigentlich eher nach Integrationsdichte, als nach
echten Engpässen.
Ich weiß nicht, was Du mit Integrationsdichte meinst.
Damit habe ich die Transitoranzahl gemeint. Ist üblich.
Ich verstehe trotzdem nicht, wie Du das Problem lösen willst, indem Du
da Transistoren hinterherwirfst.
Post by Jan Bruns
Post by Sebastian Biallas
Würde jedoch "mov eax, 1" den oberen Teil von rax erhalten, dann gibt es
Hier hast Du nun erstmal die Möglichkeit vergessen, daß man dann doch
durchaus auch movzx schreiben könnte, um exakt die obige Situation
zu konstruieren.
Also müsste man den Code mit movzx vollmachen.
Post by Jan Bruns
Post by Sebastian Biallas
Ich bin kein Prozessorhersteller, und ich kann nur die momentane
Situation reflektieren.
So wie du hier argumentierst wäre es aber doch ganz sinnig, wenn Du
wenigstens bezüglich dieses Details (zentrales execute auf "externem"
Registerspeicher) irgendwelche Zukunftserwartungen hättest.
Dann beschreib doch mal, wie es besser gehen sollte.
Post by Jan Bruns
Post by Sebastian Biallas
Post by Jan Bruns
Das hat vielleicht verschiedene Ursachen, aber einer davon ist
sicherlich memory alignment.
Nein, das hat mit Alignment nichts zu tun. Byte-Zugriffe sind
immer aligned.
Sehe ich anders, is aber echt egal.
Wie definierst Du denn Aligment? Und warum soll movzx daran etwas ändern?
--
Gruß,
Sebastian
Jan Bruns
2006-05-25 23:09:07 UTC
Permalink
Post by Sebastian Biallas
Post by Jan Bruns
Post by Sebastian Biallas
Post by Jan Bruns
Also ich kann nun nicht gerade behaupten, über die pipelinetechnsichen
Hintergründe bzgl. partieller Register genauestens informiert zu sein.
Klingt für mich eigentlich eher nach Integrationsdichte, als nach
echten Engpässen.
Ich weiß nicht, was Du mit Integrationsdichte meinst.
Damit habe ich die Transitoranzahl gemeint. Ist üblich.
Ich verstehe trotzdem nicht, wie Du das Problem lösen willst, indem Du
da Transistoren hinterherwirfst.
Vielleicht so, wie es gemacht wird, wenn ich bspw. in 32-Bit Code
"and eax,ebx" schreibe. Wenn im gleichen Code irgendwo "and ax,bx"
steht, und genau das die Pipeline verwirrt, dann hat da doch wohl
höchstwahrscheinlich irgendwer keine Lust gehabt, sich um solche
Details zu kümmern.

Klar, in den Broschüren der Hersteller heisst "keine Lust gehabt"
dann auch gerne mal "technisch notwendig" (sorry, ich hatte in letzter
Zeit etwas viel mit GPUs zu tun, da sehen die Hersteller sowas noch
recht "locker").
Post by Sebastian Biallas
Post by Jan Bruns
So wie du hier argumentierst wäre es aber doch ganz sinnig, wenn Du
wenigstens bezüglich dieses Details (zentrales execute auf "externem"
Registerspeicher) irgendwelche Zukunftserwartungen hättest.
Dann beschreib doch mal, wie es besser gehen sollte.
Von sollen hab' ich nix geschrieben.
Ich schrieb was von: könnte sein, daß das auch anders gut geht.
Weiß ich doch nicht. Bin kein CPU-Hersteller. Du auch nicht,
schreibst Du. Von daher kämen wir besser mit'nander aus,
wenn Du statt

| Das gilt auch weiterhin. Allerdings gilt danach (rax&0xffffffff00000000)==0.
|
| Das ist aber auch sinnvoll so. Obiges Verhalten war vor 20 Jahren
| vielleicht noch verständlich, ist aber für heutige Prozessoren sehr
| schlecht, weil man mit den partial register stalls umgehen muss.

besser sowas schriebest:

< Das gilt auch weiterhin. Allerdings gilt danach (rax&0xffffffff00000000)==0.
<
< Das soll für moderne CPUs aktuell technisch sinnvoll sein, weil dann...
< [Ausführung zum Thema zentralisierte Execute-Einheit und ihre Register].



Gruss

Jan Bruns
Sebastian Biallas
2006-05-25 23:33:32 UTC
Permalink
Post by Jan Bruns
Vielleicht so, wie es gemacht wird, wenn ich bspw. in 32-Bit Code
"and eax,ebx" schreibe. Wenn im gleichen Code irgendwo "and ax,bx"
steht, und genau das die Pipeline verwirrt, dann hat da doch wohl
höchstwahrscheinlich irgendwer keine Lust gehabt, sich um solche
Details zu kümmern.
Das ist natürlich möglich. Allerdings stehen Intel und AMD in
Konkurrenzkampf und keiner der beiden hat es geschafft das Problem in
soweit zu lösen, dass es "kein Problem" mehr ist.
Post by Jan Bruns
Klar, in den Broschüren der Hersteller heisst "keine Lust gehabt"
dann auch gerne mal "technisch notwendig" (sorry, ich hatte in letzter
Zeit etwas viel mit GPUs zu tun, da sehen die Hersteller sowas noch
recht "locker").
Die ISA wurde halt so angelegt, dass der "Normalfall" möglich effizient
von der CPU behandelt werden kann. Dies halte ich grundsätzlich für
nachvollziehbar und sinnvoll.
Post by Jan Bruns
Post by Sebastian Biallas
Post by Jan Bruns
So wie du hier argumentierst wäre es aber doch ganz sinnig, wenn Du
wenigstens bezüglich dieses Details (zentrales execute auf "externem"
Registerspeicher) irgendwelche Zukunftserwartungen hättest.
Dann beschreib doch mal, wie es besser gehen sollte.
Von sollen hab' ich nix geschrieben.
Ich schrieb was von: könnte sein, daß das auch anders gut geht.
Natürlich kann das sein. Da aber offenbar keiner eine Lösung dafür
kennt, hat man das Problem des partiellen Registerzugriffs bei x86_64
direkt vermieden (wie es z.B. PowerPC schon vor Jahrzehnten vorgemacht hat).
Post by Jan Bruns
Weiß ich doch nicht. Bin kein CPU-Hersteller. Du auch nicht,
schreibst Du. Von daher kämen wir besser mit'nander aus,
wenn Du statt
| Das gilt auch weiterhin. Allerdings gilt danach (rax&0xffffffff00000000)==0.
|
| Das ist aber auch sinnvoll so. Obiges Verhalten war vor 20 Jahren
| vielleicht noch verständlich, ist aber für heutige Prozessoren sehr
| schlecht, weil man mit den partial register stalls umgehen muss.
< Das gilt auch weiterhin. Allerdings gilt danach (rax&0xffffffff00000000)==0.
<
< Das soll für moderne CPUs aktuell technisch sinnvoll sein, weil dann...
< [Ausführung zum Thema zentralisierte Execute-Einheit und ihre Register].
Warum? Wenn man partiellen Registerzugriff erlaubt, dann muss die CPU
sich auch damit rumschlagen (das sollte offensichtlich sein). Und dass
es für heutige Prozessoren schlecht ist, kann man aus den Intel und AMD
Dokumentationen entnehmen.
--
Gruß,
Sebastian
Jan Bruns
2006-05-24 00:21:40 UTC
Permalink
Post by Hipo
Ich hab noch ein Problem, auf dessen Lösung ich einfachnicht komme.
Ich habe 8 Bytes in einem Register, z.B. RAX. Sie sind wie folgt
|a b c d e f g h|
|c d a b g h e f|
Also mal in 32-Bit Schreibweise (für 64 Bit lässt sich das sicherlich
einfach erweitern):

; "eax=a,b,c,d -> eax=c,d,a,b"
mov ebx,eax
and eax,$FFFF0000
and ebx,$0000FFFF
shr eax,16
shl ebx,16
or eax,ebx

oder einfach:

; "eax=a,b,c,d -> eax=c,d,a,b"
rol eax,16

letzteres is so natürlich nicht auf 64-Bit übertragbar.

Gruss

Jan Bruns
Florian Liebig
2006-06-07 13:23:25 UTC
Permalink
hi, hipo!

sieht ganz nach einem big-endian zu little-endian mit shifting
algorithmus
aus.
kennst du den damals dafuer entstandenen befehl bswap ??
vielleicht kannst du damit eleganteren code schreiben.
nur kenn ich leider die neuen 64bit register regeln nicht so genau.
aber vielleicht geht ja dies:
BSWAP rax
ROL/ROR rax,32

gruss florian.
Sebastian Biallas
2006-06-07 13:42:50 UTC
Permalink
Florian Liebig wrote:

rax = |a b c d e f g h|
Post by Florian Liebig
BSWAP rax
rax = |h g f e d c b a|
Post by Florian Liebig
ROL/ROR rax,32
rax = |d c b a h g f e|

Der OP wollte aber rax = |c d a b g h e f| erreichen...
--
Gruß,
Sebastian
Florian Liebig
2006-06-12 18:24:53 UTC
Permalink
hi sebastian!

na klar, wie du sagst.
ich habe mich in seinem post etwas verlesen.
Herbert Glarner
2006-07-15 16:05:38 UTC
Permalink
Post by Hipo
|a b c d e f g h|
|c d a b g h e f|
Wie auch immer die 64bit-Dinger heissen mögen:

A = B [abcdefgh]
A linksrotate 16 bit [cdefghab]
B rechtsrotate 16 bit [ghabcdef]
A and ffff0000ffff0000 [cd--gh--]
B and 0000ffff0000ffff [--ab--ef]
A or B [cdabghef]

Schneller kanns nicht wirklich gehen.

Freundliche Grüsse
//Herbert Glarner
--
http://herbert.wikispaces.com
Loading...