Die ARM hat einen Fortschritt durchgemacht:
- Eine 32-Bit-Befehlsarchitektur mit umfangreicherem Code als viele andere Architekturen, die jedoch schnell dekodiert werden konnte und viele Operationen mit weniger Befehlen ausführen konnte als konkurrierende Architekturen
- Eine Architektur im Dual-Instruction-Format, die zwischen dem netten und leistungsstarken (aber leider etwas aufgeblähten) ARM-Befehlssatz und einem weniger leistungsstarken (aber weitaus kompakteren) 16-Bit-Befehlssatz "Thumb" wechseln könnte. Jeder Thumb-Befehl hatte einen entsprechenden ARM-Befehl, wodurch die Notwendigkeit für Programmierer, zwei Befehlssätze zu lernen, etwas minimiert wurde.
- Eine Thumb2-Architektur, die dem Thumb-Befehlssatz Anweisungen mit zwei Wörtern hinzufügte und zu einer Win-Win-Situation führte: Der typische ARM-Code enthielt eine Mischung aus Anweisungen, die nur im ARM verfügbar waren, und Anweisungen, die im Thumb verfügbar gewesen wären musste aber trotzdem als 32 Bit dargestellt werden; In Thumb2 hat ein solcher Code den Vorteil, dass einige der 32-Bit-Befehle durch 16-Bit-Befehle ersetzt werden.
- Eine Thumb-only-Architektur, die einschränkender ist als ich es mir vorgestellt hätte, die aber kleiner und billiger ist als alle anderen.
Durch die ARM-Architektur können einige anspruchsvolle Vorgänge sehr schnell ausgeführt werden - viel schneller als auf jedem anderen Chip. Zum Beispiel (mit ARM7-TDMI):
ldrh r0, [r10, # ADDR_BUS_OFS]; Adressbus des Zielsystems lesen (13 Bit)
ldrb r1, [r9, r0, lsr # 8]; Verwenden Sie die oberen Bits, um die Adresse in einer Tabelle von Handlern nachzuschlagen
add pc, r9, r1 lsl # 2; Zum entsprechenden Händler gehen
Jeder Handler wird als Byte gespeichert, das 1/4 der Adressverschiebung vom Tabellenanfang an angibt. Der Nettoeffekt ist, dass, sobald der Inhalt des Adressbusses abgerufen wurde, nur sechs Zyklen (zwei Anweisungen) erforderlich sind, um zu einem Handler zu springen, der auf den oberen fünf Bits des abgerufenen Bits basiert, wobei eine 32-Byte-Sprungtabelle verwendet wird.
Entsprechender THUMB-Code wäre eher wie folgt:
; Vorausgesetzt, wir brauchen r6 / r7 für nichts anderes, werden sie von r9 / r10 neu zugewiesen
ldrh r0, [r7, # ADDR_BUS_OFS]
mov r1, r0
lsr r1, r1, # 8; THUMB setzt voraus, dass Quelle und Ziel identisch sind
ldrb r1, [r6, r1]
lsl r1, r1, # 1; Könnte shift-left-two verwenden, wenn die Zieladressen wortgenau ausgerichtet wären
add pc, r1
Unter dem Gesichtspunkt der Codedichte ist das in Ordnung, da die Anweisungen nur halb so groß sind wie die Originale, aber nach dem Abruf neun Zyklen statt sechs Zyklen dauern würden. In einer Anwendung, in der der beobachtete Bus mit seiner eigenen Geschwindigkeit läuft, unabhängig davon, ob der ARM es geschafft hat oder nicht, sind die schnelleren ARM-Anweisungen ein großes Plus.
Im Übrigen ist Thumb2 binärkompatibel mit Thumb, was die Verwendung früherer Tools erleichtert, aber bedeutet, dass es einige Dinge gibt, die nicht so gut wie der ursprüngliche ARM sind. In ARM könnte man beispielsweise eine 8x8-Bitmap, die in vier Registern gespeichert ist, mit etwa 3 Befehlen pro zwei Bits "drehen":
movs r0, r4, lsl # 25; Setzen Sie das oberste Bit von LSB in C und das nächste Bit in N
orrcs r6, # 0x00000001
orrmi r6, # 0x00000100
In Thumb2 müssten explizite bedingte Anweisungen hinzugefügt werden:
movs r0, r4, lsl # 25; Setzen Sie das oberste Bit von LSB in C und das nächste Bit in N
itcs
orrcs r6, # 0x00000001
itmi
orrmi r6, # 0x00000100
Zeit- und Raumersparnis um netto 33% im Vergleich zu ARM; Das ist wahrscheinlich ein Worst-Case-Beispiel dafür, dass Thumb-Code weniger effizient als ARM ist, und selbst das ist nicht gerade schrecklich.
Ein weiterer kleiner Nachteil von Thumb2 gegenüber ARM: Im ARM-Code beginnen alle Anweisungen an Vollwortgrenzen, was die statische Analyse erleichtert. In Thumb2 können Befehle beliebig an Halbwortgrenzen beginnen und sich über Vollwortgrenzen erstrecken. Die statische Analyse kann daher sehr viel schwieriger sein.