Obsah
4. Load-Store pro dvojici registrů
5. Nepodmíněné skoky a skoky do subrutiny (branch and link)
7. Základní aritmetické instrukce
10. Znaménkové rozšíření operandu či rozšíření o nuly
11. Aritmetické a bitové posuny, bitová rotace
14. Další instrukce s podmínkou
1. Instrukční sada AArch64
Na předchozí článek s popisem 64bitových mikroprocesorů s architekturou AArch64 dnes navážeme, protože se budeme věnovat podrobnějšímu popisu instrukční sady. Zaměříme se spíše na zajímavější a z pohledu jiných ISA i neobvyklé instrukce a nezapomeneme ani zdůraznit význam „nulového“ registru WZR/XZR, díky jehož existenci vzniklo velké množství užitečných instrukční aliasů. Zopakujme si však nejprve seznam typů instrukcí, který je pro účely dnešního článku nepatrně rozšířen:
Skupina | Další dělení |
---|---|
Load-Store | Load-Store pro jeden registr |
Load-Store pro dvojici registrů | |
Prefetch | |
Skoky | Nepodmíněné skoky |
Skoky do subrutiny | |
Nepodmíněný skok na adresu v registru | |
Podmíněné skoky | |
ALU operace | Základní aritmetické instrukce |
Násobení a dělení | |
Logické instrukce | |
Znaménkové rozšíření operandu či rozšíření o nuly | |
Bitové operace | |
Bitové posuny | |
Aritmetické posuny | |
Podmíněné zpracování dat | |
Podmíněný výběr operandu | |
Další instrukce s podmínkou | |
Extrakce dat | |
FP operace | Přenos operandů mezi registry |
Konverze mezi různými formáty | |
Převod na celá čísla (zaokrouhlení) | |
Základní aritmetické operace | |
Výpočet minima a maxima | |
MAC (Multiply Accumulate) | |
Porovnání operandů | |
Podmíněný výběr operandu | |
SIMD operace | Aritmetické operace se skaláry |
Aritmetické operace s vektory | |
Permutace vektorů | |
Konverze dat | |
Instrukce z crypto extension (patří do SIMD) | |
Systémové instrukce | Zpracování výjimek |
Přístup k systémovým registrům | |
Implementace bariér | |
Instrukce pro jádro systému |
2. Operační kódy instrukcí
Všechny instrukce mají pevnou šířku třiceti dvou bitů. Těchto 32 bitů je rozděleno do jednotlivých bitových polí, v jejichž uspořádání je možné nalézt určitou pravidelnost. Mnoho instrukcí používá takzvaný tříadresový kód, v němž se pěti bity určuje první zdrojový registr, dalšími pěti bity druhý zdrojový registr a další pětice bitů určuje index cílového registru. Zajímavé je, že u některých instrukcí nejsou všechny bity instrukčního slova využity (alespoň prozatím), naproti tomu například u skokové instrukce B je většina bitů použita pro uložení adresy:
000x 01ii iiii iiii iiii iiii iiii iiii
Pro příklad se podívejme na způsob zakódování těchto dvou instrukcí:
add x1, x1, #0x1 sub x2, x2, #0x1
První z těchto instrukcí má kód:
0x91000421
Druhá z těchto instrukcí má kód:
0xd1000442
Při převodu do binární soustavy získáme kódy:
1001 0001 0000 0000 0000 0100 0010 0001 1101 0001 0000 0000 0000 0100 0100 0010
Zapišme si tyto kódy společně s maskami obou instrukcí:
x00x 0001 SSii iiii iiii iinn nnnd dddd 1001 0001 0000 0000 0000 0100 0010 0001 x10x 0001 SSii iiii iiii iinn nnnd dddd 1101 0001 0000 0000 0000 0100 0100 0010
„Luštění“ je relativně snadné:
x00x 0001 SSii iiii iiii iinn nnnd dddd 1001 0001 0000 0000 0000 0100 0010 0001 ^ ^^^^ dest=x1 (5 bitů) 1001 0001 0000 0000 0000 0100 0010 0001 ^^ ^^^ src=x1 (5 bitů) 1001 0001 0000 0000 0000 0100 0010 0001 ^^ ^^^^ ^^^^ ^^ immediate=0x01 (12 bitů) 1001 0001 0000 0000 0000 0100 0010 0001 ^^ shift=0x00 (konstanty) (4 bity) 1001 0001 0000 0000 0000 0100 0010 0001 ^^ ^^^^ kód instrukce
Podobné tomu bude i u instrukce SUB, kde se ovšem pracuje s registrem X2 a horní čtyři bity budou taktéž odlišné.
3. Instrukce typu Load-Store
Jak je u RISCové architektury obvyklé, nalezneme v instrukční sadě i několik instrukcí určených pro načítání dat z paměti do registrů a naopak pro ukládání obsahu registrů do paměti. Navíc některé instrukce umožňují práci nejenom s 32bitovými a 64bitovými slovy, ale i s menšími bloky dat – s bajty a šestnáctibitovými „půlslovy“:
# | Instrukce | Stručný popis |
---|---|---|
1 | LDR | načtení 32bitového či 64bitového registru z paměti |
2 | LDRB | načtení bajtu a s rozšířením na slovo (doplňují se nuly) |
3 | LDRSB | načtení bajtu se znaménkovým rozšířením |
4 | LDRH | načtení šestnáctibitového „půlslova“ s rozšířením o nuly |
5 | LDRSH | načtení šestnáctibitového „půlslova“ se znaménkovým rozšířením |
6 | LDRSW | načtení 32bitového slova se znaménkovým rozšířením do 64bitového registru |
7 | STR | uložení 32bitového či 64bitového registru do paměti |
8 | STRB | uložení bajtu z vybraného 32bitového registru |
9 | STRH | uložení šestnáctibitového „půlslova“ z vybraného 32bitového registru |
Poznámka: zdánlivě chybějící instrukce LDRW a STRW jsou již obsaženy v základních instrukcích LDR a STR, pokud použijeme 32bitový registr (u LDR se horních 32 bitů vynuluje).
Mezi podporované adresovací režimy patří i použití offsetu vůči vybranému registru či SP.
4. Load-Store pro dvojici registrů
Již v předchozím článku jsme si řekli, že u čipů s instrukční sadou AArch64 nenalezneme instrukce LDM (Load Multiple) a STM (Store Multiple), které dokážou načíst nebo uložit libovolnou skupinu až šestnácti registrů specifikovaných bitovým polem (ovšem v určeném pořadí). Naproti tomu však máme k dispozici instrukce pro načtení páru registrů, přičemž se může jednat o libovolné registry (nemusí být uloženy za sebou atd.). Zajímavé je, že u těchto instrukcí existují dvě varianty, které dávají CPU informaci o tom, zda se jedná o dočasné (temporary) úložiště (zásobníkový rámec atd.) či spíše o trvalejší uložení dat. Tuto informaci je možné použít pro řízení přístupu ke cache atd.:
# | Instrukce | Stručný popis |
---|---|---|
1 | LDP | načtení registrového páru |
2 | LDPSW | načtení dvou 32bitových slov, jejich znaménkové rozšíření a uložení do dvojice registrů |
3 | STP | uložení registrového páru |
4 | LDNP | jako LDP, ale paměťová oblast není považována za dočasnou (temporal) |
5 | STNP | jako STP, ale paměťová oblast není považována za dočasnou (temporal) |
5. Nepodmíněné skoky a skoky do subrutiny (branch with link)
U instrukční sady AArch64 je zajímavé (a současně i velmi užitečné), že základní skoková instrukce B neprovádí skok na zadanou absolutní adresu, ale na adresu relativní vůči aktuální hodnotě PC. Rozsah skoku je v takovém případě ±128 MB; větší konstantu není možné v dané konfiguraci instrukčního slova uložit. Dále pak instrukční soubor obsahuje instrukci pro skok do podprogramu s uložením návratové adresy do registru X30 (nikoli na zásobník, používáme RISCový čip) a skok na absolutní adresu uloženou ve vybraném registru. Tato instrukce existuje ve dvou variantách, které se od sebe odlišují pouze hintem pro CPU, zda se právě realizuje návrat z podprogramu (subrutiny) či obyčejný skok:
# | Instrukce | Stručný popis |
---|---|---|
1 | B | skok na adresu vypočtenou z offsetu vůči PC v rozsahu ±128 MB |
2 | BL | branch and link, stejné jako předchozí instrukce, ovšem původní hodnota PC se uloží do X30 |
3 | BR | skok na adresu uloženou v registru s hintem, že se nejedná o výskok z podprogramu |
4 | RET | jako BR, ovšem s hintem, že se jedná o výskok z podprogramu |
5 | BRL | kombinace BR + BL, tj. skok na adresu uloženou v registru + původní PC do X30 |
6. Podmíněné skoky
Jak jsme se již dozvěděli v předchozí části tohoto seriálu, je instrukční sada AArch64 hned v několika ohledech odlišná od původní 32bitové RISCové instrukční sady ARM32 (či zkráceně pouze A32). Zásadní a na první pohled viditelná odlišnost spočívá v tom, že se zredukoval počet těch strojových instrukcí, u nichž je možné použít podmínkové bity. Jen ve stručnosti si připomeňme, že v instrukční sadě ARM32 jsou v každém instrukčním slovu (každé má bez výjimky konstantní šířku třiceti dvou bitů) rezervovány čtyři nejvyšší bity, v nichž je zapsán kód podmínky, při jejímž splnění se instrukce provede. Díky této vlastnosti bylo možné v mnoha algoritmech zredukovat počet podmíněných skoků, což je v případě (dnes už nejenom) RISCových procesorů poměrně důležité.

Obrázek 1: Formáty instrukčních slov u původní 32bitové architektury ARM. Povšimněte si, že v každém instrukčním slovu jsou nejvyšší čtyři bity vyhrazeny pro uložení kódu podmínky.
Všechny podmínky jsou vyhodnoceny na základě hodnoty jednoho či (častěji) kombinací většího množství příznaků (flags). První sada podmínkových kódů se používá pro provedení či naopak neprovedení instrukce na základě hodnoty jednoho z příznakových bitů Z (zero), V (overflow) či N (negative). Poslední podmínkový kód z této skupiny má název AL (Any/Always) a značí, že se instrukce provede v každém případě. Tento podmínkový kód se tudíž většinou v assembleru ani nezapisuje, protože je považován za implicitní:
Kód | Přípona | Význam | Testovaná podmínka |
---|---|---|---|
0000 | EQ | Z == 1 | rovnost při porovnání či nulový výsledek poslední ALU operace |
0001 | NE | Z == 0 | nerovnost při porovnání či nenulový výsledek poslední ALU operace |
0100 | MI | N == 1 | výsledek je záporný |
0101 | PL | N == 0 | výsledek je kladný či 0 |
0110 | VS | V == 1 | nastalo přetečení |
0111 | VC | V == 0 | nenastalo přetečení |
1110 | AL | Any/Always | většinou se nezapisuje, implicitní podmínka |
Další čtyři podmínkové kódy se většinou používají při porovnávání dvou celých hodnot bez znaménka (unsigned integer). V těchto případech se testují stavy příznakových bitů C (carry) a Z (zero), přesněji řečeno kombinace těchto bitů:
Kód | Přípona | Význam | Testovaná podmínka |
---|---|---|---|
0010 | CS/HS | C == 1 | ≥ |
0011 | CC/LO | C == 0 | < |
1000 | HI | C == 1 & Z == 0 | > |
1001 | LS | C == 0 | Z == 1 | ≤ |
Poslední čtyři podmínkové kódy se používají pro porovnávání hodnot se znaménkem (signed). V těchto případech se namísto příznakových bitů © carry a (Z) zero testují kombinace bitů (N) negative, (V) overflow a (Z) zero:
Kód | Přípona | Význam | Testovaná podmínka |
---|---|---|---|
1010 | GE | N == V | ≥ |
1011 | LT | N ≠ V | < |
1100 | GT | Z = 0, N = V | > |
1101 | LE | Z = 1, N ≠ V | ≤ |
Procesory s architekturou AArch64 sice používají shodné podmínkové bity, ty jsou ovšem použity jen v několika pečlivě vybraných instrukcích. Příznak přetečení je, podobně jako u mnoha dalších typů procesorů, používán při aritmetických operacích (ovšem ne implicitně – jen u instrukcí končících na S – set) a testy podmínkových bitů lze provádět především u podmíněných skoků, tj. u instrukcí, jejichž mnemotechnická zkratka začíná znakem B od slova „Branch“. Rozeznáváme následující typy nepodmíněných podmíněných skoků:
# | Instrukce | Alternativní zápis |
---|---|---|
1 | B | BAL |
2 | B.EQ | BEQ |
3 | B.NE | BNE |
4 | B.MI | BMI |
5 | B.PL | BPL |
6 | B.VS | BVS |
7 | B.VC | BVC |
8 | B.CS | BCS |
9 | B.CC | BCC |
10 | B.HI | BHI |
11 | B.LS | BLS |
12 | B.GE | BGE |
13 | B.LT | BLT |
14 | B.GT | BGT |
15 | B.LE | BLE |
Poznámka: alternativní zápis je podporován například GNU Assemblerem, většinou však můžete používat obě varianty zápisu.
Další dva typy skoků jsou odvozeny od instrukcí, které známe z instrukční sady Thumb. Dochází zde k porovnání vybraného pracovního registru s nulou:
# | Instrukce | Stručný popis |
---|---|---|
1 | CBZ | Compare and Branch if Zero |
2 | CBNZ | Compare and Branch if Not Zero |
Existují ještě další dvě instrukce pro podmíněné skoky, které se jmenují TBZ (Test and Branch if Zero) a TBNZ (Test and Branch if Not Zero). Ty provádí test hodnoty vybraného bitu registru na nulu:
# | Instrukce | Stručný popis |
---|---|---|
1 | TBZ | Test and Branch if Zero |
2 | TBNZ | Test and Branch if Not Zero |
Způsob zápisu těchto instrukcí je následující:
TBZ Xn, #konstanta, návěští TBZ Wn, #konstanta, návěští TBNZ Xn, #konstanta, návěští TBNZ Wn, #konstanta, návěští
Konstanta má šířku pouze šest bitů, protože je v ní uložen index bitu pracovního registru, který se testuje na nulu či jedničku (u registrů Wn by stačilo jen pět bitů). V případě instrukce TBZ – pokud je n-tý bit registru Xn/Wn nastavený na nulu, provede se skok, v opačném případě se řízení přenese na další instrukci. V případě instrukce TBNZ je bit testován na jedničku. Vzhledem k tomu, že v instrukčním slovu je nutné kromě adresy cíle (návěští) specifikovat i číslo pracovního registru a index bitu, je tento typ skoku omezen na rozsah ±32kB, což by ovšem v praxi mělo být více než dostačující (v opačném případě lze TBZ/TBNZ zkombinovat s absolutním skokem B).
7. Základní aritmetické instrukce
Mezi základní aritmetické instrukce samozřejmě patří součet a rozdíl. Existují vždy čtyři varianty každé z těchto operací, které se od sebe liší podle toho, zda se při výpočtu nastavují příznaky (všechny čtyři) a zda se po součtu či rozdílu ještě k výsledku přičte předchozí hodnota příznaku carry:
# | Instrukce | Stručný popis |
---|---|---|
1 | ADD | 32bitový či 64bitový součet |
2 | ADC | 32bitový či 64bitový součet s carry |
3 | ADDS | jako ADD, ovšem navíc nastaví příznakové bity |
4 | ADCS | jako ADC, ovšem navíc nastaví příznakové bity |
5 | SUB | 32bitový či 64bitový rozdíl |
6 | SBC | rozdíl s přičtením carry a odečtením jedničky |
7 | SUBS | jako SUB, ovšem navíc nastaví příznakové bity |
8 | SBCS | jako SBC, ovšem navíc nastaví příznakové bity |
Kromě toho existuje hned několik instrukčních aliasů, které je možné používat v assemblerech a které jsou rozpoznány i v disassemblerech a debuggerech. Tyto aliasy využívají registr WZR (32 bitů) či XZR (64 bitů). Připomeňme si, že tento registr je při čtení vždy nulový, což je v tomto případě výhodné, protože vlastně zadarmo získáme velké množství užitečných instrukcí:
# | Instrukce | Stručný popis |
---|---|---|
1 | NEG | alias pro SUB op1, xZR, op2 (op1 = 0 – op2) |
2 | NEGS | alias pro SUBS op1, xZR, op2 (op1 = 0 – op2 + nastavení příznaků) |
3 | NGC | alias pro SBC op1, xZR, op2 (op1 = 0 – op2 + carry – 1) |
4 | NGCS | kombinace předchozích dvou instrukcí |
5 | CMP | alias pro SUBS xZR, op1, op2 (tj.výsledek se zahodí, protože do registrů WZR/XZR se nezapisuje) |
6 | CMN | alias pro ADDS xZR, op1, op2 (dtto jako předchozí instrukce) |
7 | MOV | alias pro ADD reg1, reg2, #0 (platí je při přesunu dat mezi registry) |
Poznámka: v praxi se setkáte především s aliasy CMP, CMN a hlavně pak MOV (resp. přesněji řečeno je toto jedna z mnoha variant pseudoinstrukce MOV).
8. Násobení a dělení
U čipů AArch64 nalezneme násobičku a děličku, která dokáže vynásobit jak 32bitové, tak i 64bitové operandy. Mezi podporovanými instrukcemi najdeme i obdobu DSP instrukcí Multiply-Accumulate, ovšem s tím rozdílem, že se namísto akumulátoru může použít odlišný vstupní a odlišný výstupní registr, což konkrétně znamená, že DSP operace:
acc += op2 × op3
dokáže AArch64 provést:
op1 = op2 × op3 + op4
Podívejme se nyní, které instrukce provádí násobička a dělička:
# | Instrukce | Stručný popis |
---|---|---|
1 | MUL | 32bitové či 64bitové násobení |
2 | MADD | výsledek = op2 × op3 + op4 |
3 | MSUB | výsledek = op4 – op2 × op3 |
4 | MNEG | výsledek = – op2 × op3 |
5 | SMULL | násobení hodnot se znaménkem (32×32 → 64) |
6 | SMADDL | MADD hodnot se znaménkem pro (32×32 → 64) |
7 | SMSUBL | MSUB hodnot se znaménkem pro (32×32 → 64) |
8 | SMNEGL | MNEG hodnot se znaménkem pro (32×32 → 64) |
9 | SMULH | násobení 64×64, z výsledku se vezme jen horních 64 bitů ze 128 |
10 | UMULL | násobení hodnot bez znaménka (32×32 → 64) |
11 | UMADDL | MADD hodnot bez znaménka pro (32×32 → 64) |
12 | UMSUBL | MSUB hodnot bez znaménka pro (32×32 → 64) |
13 | UMNEGL | MNEG hodnot bez znaménka pro (32×32 → 64) |
14 | UMULH | násobení 64×64, z výsledku se vezme jen horních 64 bitů ze 128 |
15 | SDIV | 32bitové či 64bitové dělení hodnot se znaménkem |
16 | UDIV | 32bitové či 64bitové dělení hodnot bez znaménka |
Poznámka: ve skutečnosti je instrukce MUL, tedy „běžné násobení“ aliasem pro instrukci MADD, v níž je třetím vstupním operandem registr WZR či XZR, tedy „konstantní nula“. Totéž platí pro instrukci MNEG, která vznikla z instrukce MSUB, u níž je opět posledním vstupním operandem nulový registr.
9. Logické instrukce
Nesmíme samozřejmě zapomenout ani na instrukce pro provedení logických operací. Nalezneme zde klasickou trojici instrukcí pro logický součin bit po bitu, logický součet bit po bitu i logickou nonekvivalenci a navíc i instrukce, v nichž je druhý vstupní operand negován. Navíc se u všech instrukcí možné druhý operand i posunout o konstantu uloženou v instrukčním slovu:
# | Instrukce | Stručný popis |
---|---|---|
1 | AND | logický součin bit po bitu |
2 | ANDS | logický součin bit po bitu + nastavení příznaků N a Z, vynulování C a V |
3 | ORR | logický součet bit po bitu |
4 | EOR | logická nonekvivalence bit po bitu |
5 | ORN | logický součet bit po bitu, druhý vstupní operand je však negován |
6 | EON | logická nonekvivalence bit po bitu, druhý vstupní operand je však negován |
Povšimněte si, že pouze instrukce ANDS nastavuje příznaky.
Podobně jako u aritmetických operací, i u operací logických lze využít registru WZR a XZR pro vytvoření instrukčních aliasů, například druhého aliasu MOV (první byl implementován přes ADD), instrukce MOVI (načtení malé konstanty) a zejména pak užitečné pseudoinstrukce TST známé i z dalších architektur:
# | Instrukce | Stručný popis |
---|---|---|
1 | MOVI | alias pro ORR reg, xZR, konstanta (tj. provede se 0 or konstanta) |
2 | MOV | alias pro ORR reg, xZR, reg (tj. provede se 0 or registr) |
3 | TST | alias pro ANDS xZR, .., .. (výsledek AND se nikam neuloží, pouze se nastaví příznaky) |
10. Znaménkové rozšíření operandu či rozšíření o nuly
Některé instrukce slouží k manipulaci se šestnáctibitovými konstantami, které se musí nějakým způsobem rozšířit na konstanty 32bitové a 64bitové. Jedná se o následující trojici instrukcí, které vždy obsahují jak již zmíněnou šestnáctibitovou konstantu, tak i druhou konstantu reprezentující posun doleva:
# | Instrukce | Stručný popis |
---|---|---|
1 | MOVZ | 16bitová konstanta může být posunuta doleva a uložena do registru |
2 | MOVN | jako předchozí instrukce, ale pracuje se s negací konstanty (po posunutí) |
3 | MOVK | načtení 16bitové konstanty, její posun a umístění do registru (bez ovlivnění dalších bitů) |
Poznámka: při práci v assembleru většinou stačí použít pseudoinstrukci MOV, kterou assembler sám dokáže rozložit na ty instrukce, které CPU skutečně dokáže zpracovat.
Další šestice instrukcí dokáže provést znaménkové či naopak bezznaménkové rozšíření bajtu, šestnáctibitového slova (u AArch64 se používá termín halfword) či 32bitového slova (word) na 64bitovou hodnotu. Bezznaménkové rozšíření pouze vynuluje horní bity registru:
# | Instrukce | Stručný popis |
---|---|---|
1 | SXTB | alias pro SBFM, znaménkové rozšíření bajtu (B=byte) |
2 | SXTH | alias pro SBFH, znaménkové rozšíření 16bitového slova (H=halfword) |
3 | SXTW | alias pro SBFH, znaménkové rozšíření 32bitového slova (W=word) |
4 | UXTB | alias pro UBFM, bezznaménkové rozšíření bajtu (B=byte) |
5 | UXTH | alias pro UBFH, bezznaménkové rozšíření 16bitového slova (H=halfword) |
6 | UXTW | alias pro UBFH, bezznaménkové rozšíření 32bitového slova (W=word) |
11. Aritmetické a bitové posuny, bitová rotace
Množina instrukcí navržených pro provedení operací aritmetického či bitového (logického) posunu je celkem přehledná. Povšimněte si navíc poslední instrukce ROR určené pro bitovou rotaci. Neexistuje zde rotace vlevo, protože ta samozřejmě odpovídá rotaci vpravo, ovšem o odlišnou hodnotu (odečtenou od 63 či 31):
# | Instrukce | Stručný popis |
---|---|---|
1 | ASR | aritmetický posun doprava až o 31/63 bitů |
2 | LSL | logický posun doleva až o 31/63 bitů |
3 | LSR | logický posun doprava až o 31/63 bitů |
4 | ROR | rotace doprava až o 31/63 bitů |
U všech předchozích instrukcí byl posun specifikován konstantou, zatímco u dalších čtyř instrukcí je posun uložen v registru (druhý vstupní operand). Hodnota tohoto registru však není použita přímo, protože se v úvahu bere jen posledních pět či šest bitů podle toho, zda se jedná o 32bitovou či 64bitovou operaci:
# | Instrukce | Stručný popis |
---|---|---|
1 | ASRV | aritmetický posun doprava až o 31/63 bitů |
2 | LSLV | logický posun doleva až o 31/63 bitů |
3 | LSRV | logický posun doprava až o 31/63 bitů |
4 | RORV | rotace doprava až o 31/63 bitů |
Poznámka: instrukce ROR je ve skutečnosti aliasem instrukce EXTR popsané v patnácté kapitole.
12. Podmíněné zpracování dat
V této kapitole se seznámíme s následujícími instrukcemi:
# | Instrukce | Stručný popis |
---|---|---|
1 | CSET | Conditional Set |
2 | CSETM | Conditional Set Mask |
První zcela novou instrukcí uvedenou až na architektuře AArch64, je instrukce nazvaná CSET neboli Conditional Set. Tato instrukce vlastně přímo odpovídá požadavkům kladeným na datový typ boolean v mnoha programovacích jazycích, v nichž je hodnota true interně reprezentována jedničkou a hodnota false nulou. Tato instrukce existuje ve dvou variantách, přičemž první varianta pracuje s 32bitovým a druhá varianta s 64bitovým operandem):
CSET Wd, condition CSET Xd, condition
Například:
CSET W3, EQ CSET W4, MI CSET X5, HI
Tato instrukce pracuje následujícím způsobem – v případě, že je podmínka zapsaná ve druhém operandu cond splněna, uloží se do cílového registru Wd či do registru Xd hodnota 1. Pokud podmínka naopak splněna není, uloží se do registru Wd či Xd hodnota 0:
cíl = condition ? 1 : 0;
Ve skutečnosti se v případě CSET jedná o alias pro instrukci CSINC popsanou dále (podmínka ovšem musí být v tomto případě negována):
CSINC Wd, WZR, WZR, invert(condition) CSINC Xd, XZR, XZR, invert(condition)
neboli:
cíl = invert(condition) ? 0 : 0+1;
Opět zde tedy využíváme vlastnosti registru WZR a XZR.
V některých případech je však nutné ukládat pravdivostní hodnoty odlišným způsobem – true bude reprezentováno hodnotou, v níž jsou všechny bity 32bitového či 64bitového slova nastaveny na jedničku (v případě celých čísel se znaménkem to odpovídá hodnotě –1), false naopak hodnotou, v níž jsou všechny bity nulové. V tomto případě lze pro nastavení namísto CSET použít instrukci CSETM:
CSETM Wd, condition CSETM Xd, condition
Ve vyšším programovacím jazyce by bylo možné napsat:
cíl = condition ? -1 : 0;
Poznámka: u 32bitového registru odpovídá –1 hodnotě 0×ffff ffff, u 64bitového registru pak hodnotě 0×ffff ffff ffff ffff.
Opět se v tomto případě jedná o aliasy, tentokrát ovšem na instrukci CSINV:
CSINV Wd, WZR, WZR, invert(condition) CSINV Xd, XZR, XZR, invert(condition)
Poznámka: slovo „mask“ v názvu instrukce skutečně poměrně přesně odpovídá jednomu způsobu použití, protože pokud platí true=-1 a false=0, lze s těmito hodnotami provádět logický součin a součet bit po bitu, a to i v případě, kdy je druhým operandem odlišná hodnota.
13. Podmíněný výběr operandu
Mezi další instrukce, v nichž se vyhodnocuje podmínka, patří:
# | Instrukce | Stručný popis |
---|---|---|
1 | CSEL | Conditional Select |
2 | CSINV | Conditional Select Invert |
3 | CSINC | Conditional Select Increment |
4 | CSNEG | Conditional Select Negate |
Užitečnou instrukcí s podmínkou je instrukce zapisovaná mnemotechnickým kódem CSEL neboli Conditional Select. I tato instrukce existuje ve dvou variantách – 32bitové a 64bitové:
CSEL Wd, Wn, Wm, condition CSEL Xd, Xn, Xm, condition
Tato instrukce pracuje následovně: pokud je podmínka splněna, uloží se do cílového registru Wd či Xd hodnota z prvního zdrojového registru Wn nebo Xn. Pokud podmínka splněna není, je do cílového registru Wd/Xd uložena hodnota z druhého zdrojového registru Wm/Xm.
Instrukce CSEL tedy nahrazuje programovou konstrukci typu:
cíl = condition ? zdroj1 : zdroj2;
Alternativní formou instrukce CSEL je instrukce CSINV neboli Conditional Select Invert:
CSINV Wd, Wn, Wm, condition CSINV Xd, Xn, Xm, condition
Tato instrukce pracuje následovně: pokud je podmínka splněna, uloží se do cílového registru Wd či Xd hodnota z prvního zdrojového registru Wn nebo Xn. Pokud podmínka splněna není, je do cílového registru Wd/Xd uložena negovaná hodnota přečtená z druhého zdrojového registru Wm/Xm.
Instrukce CSINV tedy nahrazuje programovou konstrukci typu:
cíl = condition ? zdroj1 : ~zdroj2;
Poznámka: znak ~ je používán v programovacím jazyku C a od něj odvozených jazycích pro zápis unárního operátoru negace všech bitů (jedničkový doplněk).
Zajímavá je instrukce CSINC, která kombinuje možnosti instrukce CINC a CSEL:
CSINC Wd, Wn, Wm, condition CSINC Xd, Xn, Xm, condition
Tato instrukce provádí následující činnost:
Wd = condition ? Wn : Wm+1; Xd = condition ? Xn : Xm+1;
Touto instrukcí realizována již popsaná pseudoinstrukce CSET, a to tehdy, pokud jsou oba zdrojové registry nulové (WZR a XZR). V tomto případě se do cílového registru dosadí 0 či 0+1=1:
CSINC Wd, WZR, WZR, invert(condition) CSINC Xd, XZR, XZR, invert(condition)
Instrukce nazvaná CSNEG se do jisté míry podobá instrukci CSINV, ovšem s tím rozdílem, že se namísto jedničkového doplňku (negace) používá při nesplnění podmínky dvojkový doplněk:
CSNEG Wd, Wn, Wm, condition CSNEG Xd, Xn, Xm, condition
Tato instrukce pracuje následovně: pokud je podmínka splněna, uloží se do cílového registru Wd či Xd hodnota z prvního zdrojového registru Wn nebo Xn. Pokud podmínka splněna není, je do cílového registru Wd/Xd uložena hodnota přečtená z druhého zdrojového registru Wm/Xm, u které se nejdříve změní znaménko (onen zmíněný dvojkový doplněk).
Tato instrukce tedy nahrazuje programovou konstrukci typu:
cíl = condition ? zdroj1 : -zdroj2;
14. Další instrukce s podmínkou
Poslední tři instrukce ze sady AArch64, v nichž se vyhodnocuje podmínka, jsou vypsány v tabulce pod tímto odstavcem:
# | Instrukce | Stručný popis |
---|---|---|
1 | CINC | Conditional Increment |
2 | CINV | Conditional Invert |
3 | CNEG | Conditional Negate |
Instrukce CINC je aliasem pro instrukci CSINC, ovšem s převrácenou podmínkou a shodnými zdrojovými registry:
CINC Wd, Wn, condition CINC Xd, Xn, condition
Tato instrukce provádí následující činnost (je zde jen jediný zdrojový registr):
Wd = condition ? Wn+1 : Wn; Xd = condition ? Xn+1 : Xn;
Použití této instrukce je různé, může se například použít pro realizaci příkazu continue v programovacím jazyku C.
Podobná instrukce taktéž s jedním zdrojovým registrem se jmenuje CINV:
CINV Wd, Wn, condition CINV Xd, Xn, condition
Prováděná činnost je následující (tilda znamená negaci bit po bitu):
Wd = condition ? ~Wn : Wn; Xd = condition ? ~Xn : Xn;
Ve skutečnosti se opět jedná o instrukční alias rozpoznávaný assemblery. V tomto případě lze CINV nahradit instrukcí CSINV s oběma zdrojovými registry totožnými:
CSINV Wd, Wn, Wn, invert(condition) CSINV Xd, Xn, Xn, invert(condition)
Poslední instrukce, přesněji řečeno (opět) instrukční alias se jmenuje CNEG:
CNEG Wd, Wn, condition CNEG Xd, Xn, condition
Prováděná činnost:
Wd = condition ? -Wn : Wn; Xd = condition ? -Xn : Xn;
Tento alias je možné nahradit za CSNEG s totožnými zdrojovými registry a opačně zapsanou podmínkou:
CSNEG Wd, Wn, Wn, invert(condition) CSNEG Xd, Xn, Xn, invert(condition)
15. Extrakce dat
Poslední skupina instrukcí, o níž se dnes zmíníme, slouží k takzvané extrakci dat. Jak je z tabulky patrné, mají tyto instrukce čtyři operandy, přičemž posledním operandem je konstanta 0..31 pro první instrukci či 0..63 pro instrukci druhou. Tyto dvě instrukce nejprve pomyslně spojí oba vstupní registry Wn:Wm či Xn:Xm a následně z takto vytvořeného dočasného pseudoregistru s dvojnásobnou šířkou získají 32bitové či 64bitové slovo od zadané pozice lsb:
# | Instrukce | Stručný popis |
---|---|---|
1 | EXTR Wd, Wn, Wm, #lsb | Wd = Wn:Wm<lsb+31,lsb> |
2 | EXTR Xd, Xn, Xm, #lsb | Xd = Xn:Xm<lsb+63,lsb> |
Opět platí, že díky existenci registrů WZR a XZR je možné z těchto instrukcí vytvořit různé aliasy. Taktéž je možné mít oba zdrojové registry totožné – asi nejznámějším aliasem využívajícím dva shodné zdrojové registry je již popsaná instrukce ROR (stačí si představit, jak se z registrového páru Xn:Xn vybírá 63 bitů).
16. Odkazy na Internetu
- Comparison of ARMv8-A cores
https://en.wikipedia.org/wiki/Comparison_of_ARMv8-A_cores - A64 General Instructions
http://www.keil.com/support/man/docs/armclang_asm/armclang_asm_pge1427898258836.htm - ARMv8 (AArch64) Instruction Encoding
http://kitoslab-eng.blogspot.cz/2012/10/armv8-aarch64-instruction-encoding.html - Cortex-A32 Processor
https://www.arm.com/products/processors/cortex-a/cortex-a32-processor.php - Cortex-A35 Processor
https://www.arm.com/products/processors/cortex-a/cortex-a35-processor.php - Cortex-A53 Processor
https://www.arm.com/products/processors/cortex-a/cortex-a53-processor.php - Cortex-A57 Processor
https://www.arm.com/products/processors/cortex-a/cortex-a57-processor.php - Cortex-A72 Processor
https://www.arm.com/products/processors/cortex-a/cortex-a72-processor.php - Cortex-A73 Processor
https://www.arm.com/products/processors/cortex-a/cortex-a73-processor.php - Apple A7 (SoC založen na CPU Cyclone)
https://en.wikipedia.org/wiki/Apple_A7 - System cally pro AArch64 na Linuxu
https://github.com/torvalds/linux/blob/master/include/uapi/asm-generic/unistd.h - Architectures/AArch64 (FedoraProject.org)
https://fedoraproject.org/wiki/Architectures/AArch64 - SIG pro AArch64 (CentOS)
https://wiki.centos.org/SpecialInterestGroup/AltArch/AArch64 - The ARMv8 instruction sets
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/ch05s01.html - A64 Instruction Set
https://developer.arm.com/products/architecture/instruction-sets/a64-instruction-set - Switching between the instruction sets
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/ch05s01.html - The A64 instruction set
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/ch05s01.html - Introduction to ARMv8 64-bit Architecture
https://quequero.org/2014/04/introduction-to-arm-architecture/ - MCU market turns to 32-bits and ARM
http://www.eetimes.com/document.asp?doc_id=1280803 - Cortex-M0 Processor (ARM Holdings)
http://www.arm.com/products/processors/cortex-m/cortex-m0.php - Cortex-M0+ Processor (ARM Holdings)
http://www.arm.com/products/processors/cortex-m/cortex-m0plus.php - ARM Processors in a Mixed Signal World
http://www.eeweb.com/blog/arm/arm-processors-in-a-mixed-signal-world - ARM Architecture (Wikipedia)
https://en.wikipedia.org/wiki/ARM_architecture - DSP for Cortex-M
https://developer.arm.com/technologies/dsp/dsp-for-cortex-m - Cortex-M processors in DSP applications? Why not?!
https://community.arm.com/processors/b/blog/posts/cortex-m-processors-in-dsp-applications-why-not - White Paper – DSP capabilities of Cortex-M4 and Cortex-M7
https://community.arm.com/processors/b/blog/posts/white-paper-dsp-capabilities-of-cortex-m4-and-cortex-m7 - Q (number format)
https://en.wikipedia.org/wiki/Q_%28number_format%29 - TriCore Architecture & Core
http://www.infineon.com/cms/en/product/microcontroller/32-bit-tricore-tm-microcontroller/tricore-tm-architecture-and-core/channel.html?channel=ff80808112ab681d0112ab6b73d40837 - TriCoreTM V1.6 Instruction Set: 32-bit Unified Processor Core
http://www.infineon.com/dgdl/tc_v131_instructionset_v138.pdf?fileId=db3a304412b407950112b409b6dd0352 - TriCore v2.2 C Compiler, Assembler, Linker Reference Manual
http://tasking.com/support/tricore/tc_reference_guide_v2.2.pdf - Infineon TriCore (Wikipedia)
https://en.wikipedia.org/wiki/Infineon_TriCore - C166®S V2 Architecture & Core
http://www.infineon.com/cms/en/product/microcontroller/16-bit-c166-microcontroller/c166-s-v2-architecture-and-core/channel.html?channel=db3a304312bef5660112c3011c7d01ae - Comparing four 32-bit soft processor cores
http://www.eetimes.com/author.asp?section_id=14&doc_id=1286116 - RISC-V Instruction Set
http://riscv.org/download.html#spec_compressed_isa - RISC-V Spike (ISA Simulator)
http://riscv.org/download.html#isa-sim - RISC-V (Wikipedia)
https://en.wikipedia.org/wiki/RISC-V - David Patterson (Wikipedia)
https://en.wikipedia.org/wiki/David_Patterson_(computer_scientist) - OpenRISC (oficiální stránky projektu)
http://openrisc.io/ - OpenRISC architecture
http://openrisc.io/architecture.html - Emulátor OpenRISC CPU v JavaScriptu
http://s-macke.github.io/jor1k/demos/main.html - OpenRISC (Wikipedia)
https://en.wikipedia.org/wiki/OpenRISC - OpenRISC – instrukce
http://sourceware.org/cgen/gen-doc/openrisc-insn.html - OpenRISC – slajdy z přednášky o projektu
https://iis.ee.ethz.ch/~gmichi/asocd/lecturenotes/Lecture6.pdf - Berkeley RISC
http://en.wikipedia.org/wiki/Berkeley_RISC - Great moments in microprocessor history
http://www.ibm.com/developerworks/library/pa-microhist.html - Microprogram-Based Processors
http://research.microsoft.com/en-us/um/people/gbell/Computer_Structures_Principles_and_Examples/csp0167.htm - Great Microprocessors of the Past and Present
http://www.cpushack.com/CPU/cpu1.html - A Brief History of Microprogramming
http://www.cs.clemson.edu/~mark/uprog.html - What is RISC?
http://www-cs-faculty.stanford.edu/~eroberts/courses/soco/projects/2000–01/risc/whatis/ - RISC vs. CISC
http://www-cs-faculty.stanford.edu/~eroberts/courses/soco/projects/2000–01/risc/risccisc/ - RISC and CISC definitions:
http://www.cpushack.com/CPU/cpuAppendA.html - FPGA
https://cs.wikipedia.org/wiki/Programovateln%C3%A9_hradlov%C3%A9_pole - The Evolution of RISC
http://www.ibm.com/developerworks/library/pa-microhist.html#sidebar1