mch01 schrieb am 16. April 2008 20:31
> Joachim Durchholz schrieb am 16. April 2008 18:57
>
> > > Was überläuft, sind die architected registers. Und wohin laufen sie
> > > über? In die Schattenregister. Dafür sind die 100+ davon in Athlon
> > > und Co. da. Denke ich.
> >
> > Kann nicht sein.
> > Der Compiler muss nun mal mit den vorhandenen Registern auskommen.
> > Und gegebenenfalls dann einen MOV EAX,[EBX+10] oder so machen. Und
> > schon läuft die Sache in den L1-Cache, nicht in ein Schattenregister.
> > Die sind wohl wirklich eher für die spekulative Ausführung da.
>
> [Beispiel wg. 10k-Limit gestrichen]
Das ist zwar alles richtig, aber Dein Beispiel zeigt auch nicht den
Fall, wo ihm der Registersatz überläuft. Interessanter ist ein Fall
wie
mov r0, quelle0
add r0, quelle1
mov r1, quelle2
sub r1, quelle3
add r0,r1
mov ziel,r0
Hat man nur ein r0, muss man so codieren:
mov r0,quelle0
add r0,quelle1
mov temp0,r0
mov r0,quelle2
sub r0,quelle3
mov temp1,r0
mov r0,temp0
add r0,temp1
Man kann das durch Umordnen noch verringern, aber ein Speicherzugriff
bleibt, dagegen helfen auch noch so viele Schattenregister nichts.
> Dass diese Technik in der Praxis ziemlich erfolgreich ist, sieht man
> daran, dass so viele Schattenregister (>100) in modernen x86
> vorhanden sind. Sosnt wären die nämlich wegrationalisiert.
Keine Ahnung. Das kann auch daran liegen, dass so ein Register eher
billig ist.
> > Und ich kann nur eines sagen: der 8086 war um Klassen schlechter.
> > Das ging damit los, dass Segmente grundsätzlich 64KB groß waren. Der
> > eigentliche Zweck (Speicherschutz) wurde damit schon mal nicht
> > erfüllt, es war nur eine umständliche Methode, um ein Megabyte
> > Adressraum abzudecken.
>
> Die Segmente des 8086 waren zu keiner Zeit als
> Speicherschutzmassnahme gedacht.
Doch, ursprünglich schon.
Jedenfalls habe ich mal Aussagen in dieser Richtung gelesen.
Könnte allerdings das Intel-Marketing gewesen sein, das den Begriff
"segmentierte Architektur" im Lexikon nachgeschlagen hat, statt die
Ingenieure zu fragen.
> Dazu fehlte dem 8086 die Trennung in User-/Supervisormode.
Richtig.
> Die Segmente waren für den Compiler gedacht:
>
> Code, Stack, Data.
> Weil man bei Data häufig quelle/ziel-ops hat, gab es noch ein
> "Extra"-Datasegment. Das passte wunderbar.
Soweit schon richtig.
Es wär halt schön gewesen, wenn man DS und ES problemlos hätte laden
können.
> > Weiter ging es damit, dass die Segmentadresse auf einer
> > 16-Byte-Grenze liegen musste. Und die reale Adresse damit immer
> > Segment*16+Offset war. Was hieß, dass es für jede Adresse im
> > Adressraum 2^12 verschiedene Kombinationen aus Segment und Offset
> > gab; viel Spaß, wenn man rausfinden wollte, ob zwei Adressen gleich
> > waren.
>
> Dazu wurden, wenn das überhaupt mal nötig war, die Adressen normiert.
> Ich sage "überhaupt mal", weil damals nur selten Probleme mit >64k
> Arrays auftauchten.
Ich hatte ständig Ärger mit der 64k-Grenze.
Die Mehrdeutigkeit von Adressen ist in der Praxis allerdings in der
Tat ein eher seltenes Problem gewesen. Gestört hat es in der Regel
nur dann, wenn man Speicher von mehr als 64k Größe aufteilen wollte
und darüber Buch führen musste.
> > Das Sahnehäubchen war allerdings, dass es keinen Befehl gab, um ein
> > Segmentregister direkt aus dem Hauptspeicher zu laden. [...]
>
> ? Was machten dann die Befehle "LDS" und "LES" ?
> zu LDS: "Loads 32-bit pointer from memory source to destination
> register and DS. The offset is placed in the destination register and
> the segment is placed in DS"
Da gab es irgendwelche dämlichen Randbedingungen, weswegen das dann
oft nicht einsetzbar war.
Ist aber jetzt doch schon zu lange her.
> > Und, nein, es war nicht nötig. Der 68000 ist in der gleichen Zeit
> > entstanden und war wesentlich angenehmer. 32-Bit-Register (die man,
> > wenn man wollte, auch als 8- und 16-Bit-Register ansprechen konnte,
> > aber der Prozessor lud halt mit einem einzigen Befehl nach).
>
> Nur leider ein Detail unrichtig: Der 68k kam ziemlich genau 2 Jahre
> nach dem 8086 auf dem Markt. Als tatsächlich käufliches Produkt.
Tatsächlich?
8086: 1978
68000: 1979
(Quelle: http://www.cpu-world.com/CPUs/CPU.html )
Also nur ein Jahr Unterschied.
Und ich hatte mit dem 68k zu tun, bevor IBM mit dem PC herauskam. Das
Teil war also durchaus rechtzeitig verfügbar.
> Damit sind die 29K Transistoren ggü. den ca. 70.000 Transistoren des
> 68k lt. Moore fast eine jeweilige Punktlandung.
Nur dass Moore im Grunde noch nie so richtig gestimmt hat.
(War mir auch neu.)
> Es handelt sich also um in etwa dieselbe Leistung, bezogen auf die
> Möglichkeiten der Zeit. Und nun das ganz Erstaunliche: Trotzdem war
> der 68k im Durchschnitt nur um ca. 30% schneller als der 8086. Da
> würde ich dann sagen: Eine Minderleistung ...
Es war jedenfalls mit der damaligen Compilertechnik wesentlich
einfacher, für den 68k effizienten Code erzeugen.
Der Mac lief ja dann auch recht fix.
> > Völlig orthogonal: jeder Adressierungsmodus ging mit jeder
> > Kombination aus Registern, zwischen D0, D1, ... D7 gab es keine
> > Unterschiede, zwischen A0...A7 auch nicht.
>
> Zwar richtig, aber eben nur für den Assemblerprogrammierer so richtig
> interessant. Denn damit konnte der "wild" drauflosprogrammieren, weil
> ja in der Tat alle Kombinationen gültige Befehle waren.
Das stimmt nicht. Wenn man ein Ergebnis eines Shiftbefehls, das
nunmal immer in AX rauskommt, für eine Multiplikation benötigt, die
aber nunmal immer CX mit DX multipliziert, muss auch der Compiler
immer einen MOV CX,AX generieren.
Manchmal hab ich mich dabei wirklich wie bei Sokoban gefühlt. Und
Compiler sind bei Sokoban noch schlechter als Menschen...
> > Multiplikations- und Divisionsbefehle haben für den 64-Bit-Anteil
>
> Das konnte der gar nicht, 32x32->64 war erst beim 020 möglich.
Ich erinnere mich da anders, aber ich hab meine Unterlagen zum 68k
beim vorletzten Umzug dann doch entsorgt :-)
> > Nicht wie beim 8086, wo man die Daten teilweise von AX nach BX oder
> > DX verschieben musste, weil der dusselige Multiplikationsbefehl nun
> > mal nur auf dieses eine Register losging (was auch nur widerlich war:
> > man war die meiste Zeit damit beschäftigt, mit den Registerinhalten
> > Sokoban zu spielen, weil jeder Befehl seine Daten in einem anderen
> > Register erwartete).
>
> Mit einigen Bemerkungen hast Du Recht (z.B. MUL), aber in Summe
> nicht. Was dem 68k D0-D7 sind, ist dem 8086 AX-DX, was A0-A5 sind ist
> SI/DI, A6->BP, A7->SP. Ich habe den Eindruck, dass Du vom 8086 so
> frustriert warst, dass Dir nur die Restriktionen im Gedächtnis
> geblieben sind.
Der Shift-Befehl wollte die Bitzahl immer in CX. Indirekte
Adressierung ging nur über BX und DX (ganz besonders unangenehm). Es
gab noch mehr solche Gemeinheiten, aber ich habe sie erfolgreich
verdrängt :-)
(Ein widerliches Detail: trat bei einem Stringbefehl ein Interrupt
auf, wurde nur einer der Präfixe wiederhergestellt. Da alle
Stringbefehle das REP-Präfix brauchten, hieß das in der Praxis meist,
dass man keine Segmentpräfixe verwenden konnte oder der Stringbefehl
nach einem Interrupt im falschen Präfix weitermachte. Das hat
mindestens ein Compilerhersteller nicht mitgekriegt...)
> Ich habe nichts gegen den 68k, aber man muss halt mal zur Kenntnis
> nehmen, dass dieselbe Architektur zur Zeit A unsinnig, weil zu teuer
> ist, zur Zeit B genau richtig und zur Zeit C verquer, weil veraltet.
> Da hatte Intel die bessere Hand. Und es war gar kein solcher Zufall:
> Die haben nämlich so Sachen wie Memoryfootprints vorher mal
> simuliert. Bei den damaligen Problemgrößen ist man dann mit
> 16Bit-Zeigern (dem Offsetanteil) oft besser dran, als wenn man
> jeweils 32Bit-Zeiger laden/speichern muss.
> Auch wenn der 68k das in einem Befehl kann - er braucht halt dann
> doppelt soviele Buszugriffe und doppelt soviel Speicher.
Schon richtig, aber ich bezweifle, dass die IBM-Ingenieure auf sowas
geachtet haben. Da ging es um Taktfrequenzen und Stückkosten.
> > > Intel hat durchaus auch anderes versucht: 80860, 80960 und vor
> > > "Kurzem" den Itanium. Der ja den von Dir geliebten riesigen
> > > Universalregistersatz hat.
> >
> > Tja... nur haben sie die Emulation nicht so hingekriegt, dass die
> > Leute das Ding auch haben wollten. Und billig war er wohl auch nicht
> > so recht.
>
> Beide waren nie für eine x86-Emulation gedacht.
Was dann wohl auch das Problem war.
> > Es ist halt sehr, sehr schwierig, die Prozessorarchitektur zu
> > wechseln, wenn das wichtigste Betriebssystem nun mal nicht portiert
> > wird.
>
> Mag sein. Aber trotz aller Schelte und teilweise
> "aus-dem-Bauch-heraus-Hassen" kann man ja mal drüber nachdenken, ob
> sich die x86-Architektur nicht insgesamt als erstaunlich flexibel
> erwiesen hat und immer zum richtigen Zeitpunkt einen sehr tragfähigen
> Kompromiss zwischen "innerer Architektur" und "äußeren
> Rahmenbedingungen" gefunden hat.
Flexibel war Intel eigentlich vor allem bei der
Fertigungstechnologie.
Damit haben sie die Schwierigkeiten der Architektur ausgeglichen.
Irgendwann waren die Intel-Prozessoren sogar schneller als
spezialisierte Lisp-Chips, obgleich sie die zehnfache Anzahl an
Befehlen brauchten, um das gleiche Lisp-Programm auszuführen.
> Dazu trägt natürlich bei, dass Intel/AMD hemmungslos aufsaugen, was
> sich an guten Ideen in anderen uCs so zeigt. Und warum auch nicht?
Durchaus.
> Joachim Durchholz schrieb am 16. April 2008 18:57
>
> > > Was überläuft, sind die architected registers. Und wohin laufen sie
> > > über? In die Schattenregister. Dafür sind die 100+ davon in Athlon
> > > und Co. da. Denke ich.
> >
> > Kann nicht sein.
> > Der Compiler muss nun mal mit den vorhandenen Registern auskommen.
> > Und gegebenenfalls dann einen MOV EAX,[EBX+10] oder so machen. Und
> > schon läuft die Sache in den L1-Cache, nicht in ein Schattenregister.
> > Die sind wohl wirklich eher für die spekulative Ausführung da.
>
> [Beispiel wg. 10k-Limit gestrichen]
Das ist zwar alles richtig, aber Dein Beispiel zeigt auch nicht den
Fall, wo ihm der Registersatz überläuft. Interessanter ist ein Fall
wie
mov r0, quelle0
add r0, quelle1
mov r1, quelle2
sub r1, quelle3
add r0,r1
mov ziel,r0
Hat man nur ein r0, muss man so codieren:
mov r0,quelle0
add r0,quelle1
mov temp0,r0
mov r0,quelle2
sub r0,quelle3
mov temp1,r0
mov r0,temp0
add r0,temp1
Man kann das durch Umordnen noch verringern, aber ein Speicherzugriff
bleibt, dagegen helfen auch noch so viele Schattenregister nichts.
> Dass diese Technik in der Praxis ziemlich erfolgreich ist, sieht man
> daran, dass so viele Schattenregister (>100) in modernen x86
> vorhanden sind. Sosnt wären die nämlich wegrationalisiert.
Keine Ahnung. Das kann auch daran liegen, dass so ein Register eher
billig ist.
> > Und ich kann nur eines sagen: der 8086 war um Klassen schlechter.
> > Das ging damit los, dass Segmente grundsätzlich 64KB groß waren. Der
> > eigentliche Zweck (Speicherschutz) wurde damit schon mal nicht
> > erfüllt, es war nur eine umständliche Methode, um ein Megabyte
> > Adressraum abzudecken.
>
> Die Segmente des 8086 waren zu keiner Zeit als
> Speicherschutzmassnahme gedacht.
Doch, ursprünglich schon.
Jedenfalls habe ich mal Aussagen in dieser Richtung gelesen.
Könnte allerdings das Intel-Marketing gewesen sein, das den Begriff
"segmentierte Architektur" im Lexikon nachgeschlagen hat, statt die
Ingenieure zu fragen.
> Dazu fehlte dem 8086 die Trennung in User-/Supervisormode.
Richtig.
> Die Segmente waren für den Compiler gedacht:
>
> Code, Stack, Data.
> Weil man bei Data häufig quelle/ziel-ops hat, gab es noch ein
> "Extra"-Datasegment. Das passte wunderbar.
Soweit schon richtig.
Es wär halt schön gewesen, wenn man DS und ES problemlos hätte laden
können.
> > Weiter ging es damit, dass die Segmentadresse auf einer
> > 16-Byte-Grenze liegen musste. Und die reale Adresse damit immer
> > Segment*16+Offset war. Was hieß, dass es für jede Adresse im
> > Adressraum 2^12 verschiedene Kombinationen aus Segment und Offset
> > gab; viel Spaß, wenn man rausfinden wollte, ob zwei Adressen gleich
> > waren.
>
> Dazu wurden, wenn das überhaupt mal nötig war, die Adressen normiert.
> Ich sage "überhaupt mal", weil damals nur selten Probleme mit >64k
> Arrays auftauchten.
Ich hatte ständig Ärger mit der 64k-Grenze.
Die Mehrdeutigkeit von Adressen ist in der Praxis allerdings in der
Tat ein eher seltenes Problem gewesen. Gestört hat es in der Regel
nur dann, wenn man Speicher von mehr als 64k Größe aufteilen wollte
und darüber Buch führen musste.
> > Das Sahnehäubchen war allerdings, dass es keinen Befehl gab, um ein
> > Segmentregister direkt aus dem Hauptspeicher zu laden. [...]
>
> ? Was machten dann die Befehle "LDS" und "LES" ?
> zu LDS: "Loads 32-bit pointer from memory source to destination
> register and DS. The offset is placed in the destination register and
> the segment is placed in DS"
Da gab es irgendwelche dämlichen Randbedingungen, weswegen das dann
oft nicht einsetzbar war.
Ist aber jetzt doch schon zu lange her.
> > Und, nein, es war nicht nötig. Der 68000 ist in der gleichen Zeit
> > entstanden und war wesentlich angenehmer. 32-Bit-Register (die man,
> > wenn man wollte, auch als 8- und 16-Bit-Register ansprechen konnte,
> > aber der Prozessor lud halt mit einem einzigen Befehl nach).
>
> Nur leider ein Detail unrichtig: Der 68k kam ziemlich genau 2 Jahre
> nach dem 8086 auf dem Markt. Als tatsächlich käufliches Produkt.
Tatsächlich?
8086: 1978
68000: 1979
(Quelle: http://www.cpu-world.com/CPUs/CPU.html )
Also nur ein Jahr Unterschied.
Und ich hatte mit dem 68k zu tun, bevor IBM mit dem PC herauskam. Das
Teil war also durchaus rechtzeitig verfügbar.
> Damit sind die 29K Transistoren ggü. den ca. 70.000 Transistoren des
> 68k lt. Moore fast eine jeweilige Punktlandung.
Nur dass Moore im Grunde noch nie so richtig gestimmt hat.
(War mir auch neu.)
> Es handelt sich also um in etwa dieselbe Leistung, bezogen auf die
> Möglichkeiten der Zeit. Und nun das ganz Erstaunliche: Trotzdem war
> der 68k im Durchschnitt nur um ca. 30% schneller als der 8086. Da
> würde ich dann sagen: Eine Minderleistung ...
Es war jedenfalls mit der damaligen Compilertechnik wesentlich
einfacher, für den 68k effizienten Code erzeugen.
Der Mac lief ja dann auch recht fix.
> > Völlig orthogonal: jeder Adressierungsmodus ging mit jeder
> > Kombination aus Registern, zwischen D0, D1, ... D7 gab es keine
> > Unterschiede, zwischen A0...A7 auch nicht.
>
> Zwar richtig, aber eben nur für den Assemblerprogrammierer so richtig
> interessant. Denn damit konnte der "wild" drauflosprogrammieren, weil
> ja in der Tat alle Kombinationen gültige Befehle waren.
Das stimmt nicht. Wenn man ein Ergebnis eines Shiftbefehls, das
nunmal immer in AX rauskommt, für eine Multiplikation benötigt, die
aber nunmal immer CX mit DX multipliziert, muss auch der Compiler
immer einen MOV CX,AX generieren.
Manchmal hab ich mich dabei wirklich wie bei Sokoban gefühlt. Und
Compiler sind bei Sokoban noch schlechter als Menschen...
> > Multiplikations- und Divisionsbefehle haben für den 64-Bit-Anteil
>
> Das konnte der gar nicht, 32x32->64 war erst beim 020 möglich.
Ich erinnere mich da anders, aber ich hab meine Unterlagen zum 68k
beim vorletzten Umzug dann doch entsorgt :-)
> > Nicht wie beim 8086, wo man die Daten teilweise von AX nach BX oder
> > DX verschieben musste, weil der dusselige Multiplikationsbefehl nun
> > mal nur auf dieses eine Register losging (was auch nur widerlich war:
> > man war die meiste Zeit damit beschäftigt, mit den Registerinhalten
> > Sokoban zu spielen, weil jeder Befehl seine Daten in einem anderen
> > Register erwartete).
>
> Mit einigen Bemerkungen hast Du Recht (z.B. MUL), aber in Summe
> nicht. Was dem 68k D0-D7 sind, ist dem 8086 AX-DX, was A0-A5 sind ist
> SI/DI, A6->BP, A7->SP. Ich habe den Eindruck, dass Du vom 8086 so
> frustriert warst, dass Dir nur die Restriktionen im Gedächtnis
> geblieben sind.
Der Shift-Befehl wollte die Bitzahl immer in CX. Indirekte
Adressierung ging nur über BX und DX (ganz besonders unangenehm). Es
gab noch mehr solche Gemeinheiten, aber ich habe sie erfolgreich
verdrängt :-)
(Ein widerliches Detail: trat bei einem Stringbefehl ein Interrupt
auf, wurde nur einer der Präfixe wiederhergestellt. Da alle
Stringbefehle das REP-Präfix brauchten, hieß das in der Praxis meist,
dass man keine Segmentpräfixe verwenden konnte oder der Stringbefehl
nach einem Interrupt im falschen Präfix weitermachte. Das hat
mindestens ein Compilerhersteller nicht mitgekriegt...)
> Ich habe nichts gegen den 68k, aber man muss halt mal zur Kenntnis
> nehmen, dass dieselbe Architektur zur Zeit A unsinnig, weil zu teuer
> ist, zur Zeit B genau richtig und zur Zeit C verquer, weil veraltet.
> Da hatte Intel die bessere Hand. Und es war gar kein solcher Zufall:
> Die haben nämlich so Sachen wie Memoryfootprints vorher mal
> simuliert. Bei den damaligen Problemgrößen ist man dann mit
> 16Bit-Zeigern (dem Offsetanteil) oft besser dran, als wenn man
> jeweils 32Bit-Zeiger laden/speichern muss.
> Auch wenn der 68k das in einem Befehl kann - er braucht halt dann
> doppelt soviele Buszugriffe und doppelt soviel Speicher.
Schon richtig, aber ich bezweifle, dass die IBM-Ingenieure auf sowas
geachtet haben. Da ging es um Taktfrequenzen und Stückkosten.
> > > Intel hat durchaus auch anderes versucht: 80860, 80960 und vor
> > > "Kurzem" den Itanium. Der ja den von Dir geliebten riesigen
> > > Universalregistersatz hat.
> >
> > Tja... nur haben sie die Emulation nicht so hingekriegt, dass die
> > Leute das Ding auch haben wollten. Und billig war er wohl auch nicht
> > so recht.
>
> Beide waren nie für eine x86-Emulation gedacht.
Was dann wohl auch das Problem war.
> > Es ist halt sehr, sehr schwierig, die Prozessorarchitektur zu
> > wechseln, wenn das wichtigste Betriebssystem nun mal nicht portiert
> > wird.
>
> Mag sein. Aber trotz aller Schelte und teilweise
> "aus-dem-Bauch-heraus-Hassen" kann man ja mal drüber nachdenken, ob
> sich die x86-Architektur nicht insgesamt als erstaunlich flexibel
> erwiesen hat und immer zum richtigen Zeitpunkt einen sehr tragfähigen
> Kompromiss zwischen "innerer Architektur" und "äußeren
> Rahmenbedingungen" gefunden hat.
Flexibel war Intel eigentlich vor allem bei der
Fertigungstechnologie.
Damit haben sie die Schwierigkeiten der Architektur ausgeglichen.
Irgendwann waren die Intel-Prozessoren sogar schneller als
spezialisierte Lisp-Chips, obgleich sie die zehnfache Anzahl an
Befehlen brauchten, um das gleiche Lisp-Programm auszuführen.
> Dazu trägt natürlich bei, dass Intel/AMD hemmungslos aufsaugen, was
> sich an guten Ideen in anderen uCs so zeigt. Und warum auch nicht?
Durchaus.