Obsah
1. RISCové mikroprocesory s komprimovanými instrukčními sadami (2)
3. Kódování instrukcí různé šířky v architektuře RISC-V
4. Kódování instrukcí při použití RVC
5. Formát instrukcí typu CL (LOAD)
6. Formát instrukcí typu CS (STORE)
7. Formát instrukcí typu CB (BRANCH)
8. Formát instrukcí typu CJ (JUMP)
9. Formát instrukcí typu CR (REGISTER)
10. Formát instrukcí typu CI (IMMEDIATE)
11. Formát instrukcí typu CCS (stack-relative store)
12. Formát instrukcí typu CIW (WIDE IMMEDIATE)
13. Výsledky měření: zmenšení velikosti kódu použitím RVC
1. RISCové mikroprocesory s komprimovanými instrukčními sadami (2)
„The majority of today's processors can’t rightfully be called completely RISC or completely CISC. The two textbook architectures have evolved towards each other to such an extent that there’s no longer a clear distinction between their respective approaches to increasing performance and efficiency.“
V předchozí části seriálu o mikroprocesorech s architekturou RISC jsme si uvedli několik důvodů, proč se u některých RISCových architektur (většinou těch komerčně úspěšných, což pravděpodobně nebude úplná náhoda :-) kromě původní čistě RISCové instrukční sady zavedla i instrukční sada s „komprimovanými“ instrukcemi, což v kontextu klasických RISCových mikroprocesorů znamená instrukce s šířkou osmi, ovšem většinou šestnácti bitů (alternativně též kombinace 16bitových a 32bitových instrukcí). Tyto komprimované instrukční sady se zpočátku začaly uplatňovat především v těch oblastech, kde lze použít pouze cache o relativně malé kapacitě a kde je přístup do paměti instrukcí pomalý (to platí zejména pro embedded zařízení vybavená Flash ROM, přeneseně pak i pro mikrořadiče). Zajímavé však je, že dnes tyto instrukční sady našly své uplatnění i v dalších oblastech, například u tabletů atd. To souvisí mj. i s neustále se zvětšujícím rozdílem mezi rychlostí CPU a dobou přístupu do pamětí (tento rozdíl se vlastně ještě násobí s tím, jak roste počet procesorových jader).
První popsanou „komprimovanou“ instrukční sadou byla sada MIPS16e používaná u některých mikroprocesorů s architekturou MIPS. Dnes si přiblížíme zejména možnosti, které v této oblasti nabízí progresivní architektura RISC-V, jejíž možnosti se neustále rozvíjejí a především je navržena tak, aby se RISC-V mohla rozvíjet několika směry. Popisem architektury RISC-V z pohledu programátora jsme se již zabývali v předchozích částech tohoto seriálu [1] [2] [3] a [4]. Vysvětlili jsme si princip kódování instrukcí i způsob vytváření nových rozšiřujících instrukčních sad. Poměrně specifická je v tomto ohledu především instrukční sada označená písmenem „C“, která je též nazývána RVC (RISC-V Compressed). Specifičnost instrukční sady „C“ spočívá v tom, že se v ní pracuje s instrukcemi o šířce šestnácti bitů a nikoli 32 bitů; navíc se v instrukčních slovech aktivně používají i nejnižší dva bity kódu instrukce (ty mají pro 32bitové instrukce hodnotu 11).
Pro malé připomenutí: v rámci projektu RISC-V již bylo navrženo a implementováno větší množství vzájemně se doplňujících instrukčních sad, zejména pak:
Označení | Význam |
---|---|
Oficiální sady instrukcí | |
I | aritmetické instrukce (32/64 bit), load/store, skoky, rozvětvení, speciální operace |
M | rozšíření o instrukce pro násobení a dělení |
A | atomické operace typu read-modify-write (využitelné zejména pro multicore) |
F | operace s hodnotami typu float/single (jednoduchá přesnost) |
D | operace s hodnotami typu double (dvojitá přesnost) |
Další rozšíření | |
Q | operace s hodnotami typu quad (čtyřnásobná přesnost) |
L | decimální aritmetika |
C | komprimované instrukce (viz též navazující kapitoly) |
B | bitové operace |
T | podpora pro transakční paměť |
P | SIMD operace |
2. RVC (RISC-V – C)
„Leveraging 25 years of hindsight, RISC-V was designed to support compressed instructions from the start, leaving enough opcode space for RVC and many other extensions“
Tvůrci formátu instrukcí pro mikroprocesory RISC-V nezapomněli ani na to, že se tato procesorová jádra budou s velkou pravděpodobností používat mj. i v embedded systémech, kde se z různých důvodů (již zmíněná pomalá paměť Flash, relativně malá kapacita instrukční cache apod.) preferuje mít možnost vytvářet kód s větší hustotou, a to i za cenu menší výkonnosti celého čipu. Pro tyto účely byla navržena prozatím neoficiální instrukční sada „C“ nazývaná též RVC (RISC-V Compressed) s instrukcemi o šířce 16 bitů a nikoli 32 bitů. Tato instrukční sada byla vytvořena s tím, že se bude jednat o doplněk ke stávajícím instrukčním sadám, nebude tedy nutné provádět přepínání mezi různými režimy činnosti (na rozdíl od Thumb atd.).
Designéři architektury RISC-V se tak poučili z některých problémů, které dříve doprovázely jejich konkurenty, a to jak ARM (nutnost explicitního přepínání mezi A32 a Thumb, opuštění této kombinace v AArch64) tak i x86_64 (komplikace mikroprocesoru s instrukční sadou s instrukcemi proměnné délky). Podle soudobých měření se zdá, že instrukční sada „C“ může přinést zmenšení strojového kódu o přibližně 25 až 30%, což dále vede ke snížení výpadků instrukční cache o 20 až 25% (zde je ovšem nutné podotknout, že do značné míry záleží na podpoře v překladačích a JIT, tato podpora stále není dokonalá, takže lze předpokládat další zlepšení).
Mimochodem, podobně jako je dnes většinou nemožné najít prakticky používaný mikroprocesor s čistým CISC designem či naopak čistý RISC procesor, je i problematika měření hustoty binárních aplikací poměrně komplikovaná a jako taková je možné i měření provést šikovně takovým způsobem, aby bylo možné prosazovat vlastní výrobek (mikroprocesor) na úkor konkurence. Pěkně je to vidět například na následujících dvou zprávách, které se bez dalších podrobností zmiňují o rozdílech mezi architekturami ARM a MIPS: [1] [2]. I z tohoto důvodu je nutné počkat na měření založeném na široké bázi projektů (například celé Linuxové distro) a porovnat vlastnosti RVC s Thumb, Thumb 2 či MIPS16e.
3. Kódování instrukcí různé šířky v architektuře RISC-V
„Size matters.“
Připomeňme si nejprve již zmíněný způsob kódování instrukcí v mikroprocesorových jádrech s architekturou RISC-V. Ten je navržen takovým způsobem, aby byla instrukční sada velmi snadno rozšiřitelná, a to i kdykoli v budoucnosti. V RISC-V se pro základní rozlišení mezi „komprimovanými“ šestnáctibitovými instrukcemi a instrukcemi větší šířky používají nejnižší dva bity instrukčního slova, které pro plnohodnotné RISCové 32bitové instrukce obsahují dvojici jedniček a pro komprimované instrukce 16bitové pak jednu z kombinací 00, 01, 10. Dekodér tedy může jen na základě hodnot těchto dvou bitů velmi snadno určit, jakým způsobem má instrukci zpracovat (RISC-V je little endian, což je zde poměrně důležité):
15 0 +----------------+ |xxxxxxxxxxxxxxaa| aa != 11 +----------------+
Ve skutečnosti však jdou možnosti RISC-V ještě mnohem zajímavější (i když prozatím příliš nevyužívané), neboť z dalších bitů operačního kódu instrukce lze zjistit, zda má instrukce šířku 32bitů či zda je dokonce ještě širší. Používá se následující způsob kódování, který teoreticky umožňuje tvořit instrukce o šířce až 320bitů, což by pravděpodobně vedlo k monstróznímu čipu s architekturou VLIW (i když: těžko říct, možnosti překladačů jsou dnes dosti značné v porovnání s dobou, kdy VLIW začínalo). Nás bude samozřejmě zajímat především kódování 32bitových operačních kódů, které vypadá následovně:
31 16 15 0 +----------------+----------------+ |xxxxxxxxxxxxxxxx|xxxxxxxxxxxbbb11| bb != 111 +----------------+----------------+
Pro (prozatím) teoretické instrukce o šířce 48 bitů, které dnes neexistují, se používá tento formát:
47 32 31 16 15 0 +----------------+----------------+----------------+ |xxxxxxxxxxxxxxxx|xxxxxxxxxxxxxxxx|xxxxxxxxxx011111| +----------------+----------------+----------------+
A konečně pro instrukce s operačním kódem dlouhým 64 bitů by se použil následující formát:
63 48 47 32 31 16 15 0 +----------------+----------------+----------------+----------------+ |xxxxxxxxxxxxxxxx|xxxxxxxxxxxxxxxx|xxxxxxxxxxxxxxxx|xxxxxxxxx0111111| +----------------+----------------+----------------+----------------+
Poznámka: šířka operačních kódů instrukcí žádným způsobem neurčuje šířku operandů. To, že základní instrukční sada RISC-V, resp. přesněji řečeno RVI32, používá instrukce o šířce 32 bitů a operandy o šířce taktéž 32 bitů, je z tohoto pohledu vlastně „náhoda“. Ostatně vzpomeňme například na již zmíněnou architekturu A32 (ARM) s instrukční sadou Thumb (32bitové operandy, 16bitové instrukce) či A64 (AArch64) s 64bitovými operandy a 32bitovými instrukcemi.
4. Kódování instrukcí při použití RVC
Aby bylo možné zakódovat instrukce, které měly původně šířku 32 bitů do pouhých šestnácti bitů, museli tvůrci provést stejné změny v instrukční sadě, s jakými jsme se již setkali minule:
- Zmenšit počet pracovních registrů použitelných u některých instrukcí (někdy se jedná pouze o osm registrů x8 až x15, jiné instrukce pracují se všemi 32 registry, tj. včetně nulového registru).
- Zmenšit šířku konstant, některé konstanty jsou automaticky násobeny 4× či 8×.
- Sjednotit jeden zdrojový registr s registrem cílovým (dvouadresový kód).
- Některé instrukce bylo nutné vynechat (musí se tedy použít jejich „široká“ varianta).
Najdeme zde ovšem i poměrně důležitou změnu: v instrukční sadě jsou zahrnuty instrukce pro načtení a ukládání dat do registrů matematického koprocesoru. Tvůrci instrukční sady argumentují tím, že tyto instrukce jsou používány velmi často a proto si zaslouží být součástí komprimované instrukční sady. I zde bylo nutné snížit počet adresovatelných registrů, a to konkrétně na registry f8 až f15 (což koreluje s podmnožinou celočíselných registrů x8 až x15).
V rámci komprimované instrukční sady „C“ se používá celkem osm různých formátů instrukčních slov:
# | Zkratka | Význam | Poznámka |
---|---|---|---|
1 | CL | instrukce typu LOAD | lze použít osm pracovních registrů x8..x15 |
2 | CS | instrukce typu STORE | lze použít osm pracovních registrů x8..x15 |
3 | CB | rozvětvení (BRANCH) | lze použít osm pracovních registrů x8..x15 |
4 | CJ | skok (JUMP) | nepoužívá se žádný registr, pouze adresa skoku |
5 | CR | operace s registry (REGISTER) | lze použít jakýkoli registr |
6 | CI | operace s konstantou (IMMEDIATE) | lze použít jakýkoli registr |
7 | CCS | stack-relative store | lze použít jakýkoli registr |
8 | CIW | WIDE IMMEDIATE | lze použít osm pracovních registrů x8..x15 |
Jednotlivé formáty instrukcí jsou podrobněji popsány v navazujících kapitolách.
5. Formát instrukcí typu CL (LOAD)
První formát instrukcí, s nímž se dnes setkáme, je formát používaný většinou základních instrukcí typu LOAD, tj. instrukcí, které slouží pro načtení operandu do vybraného pracovního registru. Instrukce používající formát CL mají instrukční slovo rozděleno na tato bitová pole:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |function| imm | rs1 | imm | rd | op | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Význam jednotlivých bitových polí:
# | Bitové pole | Význam |
---|---|---|
1 | function | kód prováděné operace |
2 | imm | offset rozdělený na dvě části |
3 | rs1 | index registru, v němž je uložena bázová adresa, může se jednat o registr x8 až x15 |
4 | rd | index cílového registru, do něhož se uloží načtená data, registry x8 až x15 či f8 až f15 |
5 | op | obsahuje kód C0 |
Podporovány jsou tyto instrukce:
# | Instrukce | Popis |
---|---|---|
1 | C.LW | načtení 32bitového slova z adresy offset×4+rs1 |
2 | C.LD | načtení 64bitového slova z adresy offset×8+rs1 |
3 | C.LQ | načtení 128bitového slova z adresy offset×16+rs1 |
4 | C.FLW | načtení 32bitové hodnoty typu float z adresy offset×4+rs1 |
5 | C.FLD | načtení 64bitové hodnoty typu double z adresy offset×8+rs1 |
Na tomto místě je důležité si uvědomit, že pouze některé instrukce mohou být podporovány zvoleným čipem (což ostatně platí i pro dále popsané instrukce). Například jen čipy s matematickým koprocesorem podporují instrukce C.FLW a C.FLD, na čistě 32bitových čipech nebudou podporovány instrukce C.LD a C.LQ atd. Jediná univerzální instrukce je zde C.LW.
6. Formát instrukcí typu CS (STORE)
Opakem instrukcí typu LOAD jsou samozřejmě instrukce typu STORE sloužící pro uložení obsahu vybraného pracovního registru (či registru matematického koprocesoru) na zvolenou adresu operační paměti:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |function| imm | rs1 | imm | rs2 | op | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Význam jednotlivých bitových polí:
# | Bitové pole | Význam |
---|---|---|
1 | function | kód prováděné operace |
2 | imm | offset rozdělený na dvě části |
3 | rs1 | index registru, v němž je uložena bázová adresa, může se jednat o registr x8 až x15 |
4 | rs2 | index registru obsahujícího data, která se mají uložit, registry x8 až x15 či f8 až f15 |
5 | op | obsahuje kód C0 |
Podporovány jsou tyto instrukce:
# | Instrukce | Popis |
---|---|---|
1 | C.SW | uložení 32bitového slova na adresu offset×4+rs1 |
2 | C.SD | uložení 64bitového slova na adresu offset×8+rs1 |
3 | C.SQ | uložení 128bitového slova na adresu offset×16+rs1 |
4 | C.FSW | uložení 32bitové hodnoty typu float na adresu offset×4+rs1 |
5 | C.FSD | uložení 64bitové hodnoty typu double na adresu offset×8+rs1 |
Navíc sem spadají i aritmeticko-logické instrukce používající jen registry x8 až x15:
# | Instrukce | Popis |
---|---|---|
1 | C.AND | operace AND |
2 | C.OR | operace OR |
3 | C.XOR | operace XOR |
4 | C.SUB | rozdíl |
5 | C.ADDW | součet se znaménkovým rozšířením výsledku před zápisem |
6 | C.SUBW | rozdíl se znaménkovým rozšířením výsledku před zápisem |
7. Formát instrukcí typu CB (BRANCH)
Instrukce sloužící pro provedení podmíněného rozvětvení, tj. instrukce typu BRANCH, používají další specifický instrukční formát, který se odlišuje od již popsaných formátů:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |function| offset | rs1 | offset | op | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Význam jednotlivých bitových polí:
# | Bitové pole | Význam |
---|---|---|
1 | function | kód prováděné operace |
2 | offset | offset rozdělený na dvě části |
3 | rs1 | index registru, jehož hodnota je porovnána s nulou |
4 | op | obsahuje kód C1 |
Tento formát je podporovaný dvěma instrukcemi:
# | Instrukce | Popis |
---|---|---|
1 | C.BEQZ | pokud je registr rs1 roven nule, provede se skok na adresu PC+offset (&plusm;256 bajtů) |
2 | C.BNEZ | pokud není registr rs1 roven nule, provede se skok na adresu PC+offset (&plusm;256 bajtů) |
Povšimněte si, že další skoky (či větvení) s podmínkou nejsou v instrukční sadě „C“ podporovány; navíc zde existuje omezení na skoky v relativním rozsahu &plusm;256 bajtů. Pokud je zapotřebí skočit dál, musí překladač sám použít buď dvojici C.J+BxxZ či se uchýlit k použití „plnohodnotné“ instrukce RV32I či RV64I.
Navíc se tento formát používá i u instrukcí pro posun doprava (tyto instrukce se již nikam jinam nevešly, proto je část operačního kódu uložena v prvním bitovém poli s offsetem):
# | Instrukce | Popis |
---|---|---|
1 | C.SRLI | bitový posun registru rd/rs1 doprava |
2 | C.SRAI | aritmetický posun registru rd/rs1 doprava |
3 | C.ANDI | bitový součin |
8. Formát instrukcí typu CJ (JUMP)
Instrukce pro nepodmíněný skok používají odlišný formát, než tomu bylo u instrukcí typu BRANCH. Povšimněte si, že se zde již nepoužívá žádný index zdrojového registru:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |function| adresa skoku | op | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Význam jednotlivých bitových polí:
# | Bitové pole | Význam |
---|---|---|
1 | function | kód prováděné operace |
2 | adresa skoku (relativní v rozsahu &plusm;2kB) | |
3 | op | obsahuje kód C1 |
Tento formát je opět podporovaný pouze dvěma instrukcemi, a to konkrétně instrukcemi C.J a C.JAL:
# | Instrukce | Popis |
---|---|---|
1 | C.J | provede se skok na adresu PC+offset (&plusm;2kB) |
2 | C.JAL | provede se skok na adresu PC+offset (&plusm;2kB) + uložení návratové adresy do registru x1 |
Instrukce C.JAL je zajímavá, protože implicitně adresuje registr x1 pro uložení návratové adresy. V případě, že se mají skoky provádět na libovolnou adresu, je nutné použít instrukce C.JR a C.JALR, které však využívají odlišný instrukční formát.
9. Formát instrukcí typu CR (REGISTER)
Tento formát je využíván mnoha instrukcemi, které potřebují adresovat dva zdrojové registry popř. jeden zdrojový registr a jeden registr cílový. Speciálním případem jsou instrukce skoku C.JR a C.JALR, u nichž se používá jen jediný zdrojový registr (druhý zdrojový registr je nulový):
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ | function | rd/rs1 | rs2 | op | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Význam jednotlivých bitových polí:
# | Bitové pole | Význam |
---|---|---|
1 | function | kód prováděné operace |
2 | rd/rs1 | první zdrojový registr či cílový registr |
3 | rs2 | druhý zdrojový registr či nula (u skoků) |
4 | op | obsahuje kód C0 či C2 |
Tento formát používají instrukce provádějící různé operace, proto je tabulka složitější, než v předchozích kapitolách:
# | Instrukce | Popis |
---|---|---|
1 | C.JR | skok na adresu uloženou v registru rs1, rs2 musí být nulový |
2 | C.JALR | podobně C.JR, jen navíc uloží návratovou hodnotu do registru x1 |
3 | C.MV | přesun dat mezi registry, kromě x0 |
4 | C.ADD | součet (kromě x0, což je logické) |
5 | C.EBREAK | kódován jako C.ADD s x0,x0 |
Poznámky:
- Zdrojový registr může být jakýkoli, tj. x0 až x31.
- Cílový registr může být jakýkoli kromě nuly, tj. x1 až x31.
- U instrukcí skoků C.JR a C.JALR musí být index registru rs2 nulový, jinak by se změnil operační kód instrukce.
10. Formát instrukcí typu CI (IMMEDIATE)
Všechny instrukce, u nichž je zapotřebí použít jeden zdrojový nebo cílový registr a konstantu, používají formát CI:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |function|im| rd/rs1 | imm | op | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Význam jednotlivých bitových polí:
# | Bitové pole | Význam |
---|---|---|
1 | function | kód prováděné operace |
2 | imm | konstanta (má různý význam podle typu instrukce) |
3 | rd/rs1 | index zdrojového nebo cílového registru |
4 | op | obsahuje kód C1 nebo C2 |
Tento formát používají instrukce provádějící různé operace, proto je tabulka opět složitější, než v předchozích kapitolách:
# | Instrukce | Popis |
---|---|---|
1 | C.LWSP | načtení 32bitového slova z adresy x2+offset×4 s uložením výsledku do registru rd |
2 | C.LDSP | načtení 64bitového slova z adresy x2+offset×8 s uložením výsledku do registru rd |
3 | C.LQSP | načtení 128bitového slova z adresy x2+offset×16 s uložením výsledku do registru rd |
4 | C.FLWSP | načtení 32bitového slova (float) z adresy x2+offset×4 s uložením výsledku do registru rd |
5 | C.FLDSP | načtení 64bitového slova (double) z adresy x2+offset×8 s uložením výsledku do registru rd |
6 | C.LI | znaménkové rozšíření šestibitové konstanty a uložení do registru rd |
7 | C.LUI | bezznaménkové rozšíření šestibitové konstanty a uložení do registru rd na bity 12..17 |
8 | C.ADDI | přičtení konstanty (zdrojový registr=cílový registr) |
9 | C.ADDIW | přičtení konstanty a rozšíření na 64bitů (zdrojový registr=cílový registr) |
10 | C.ADDI16SP | podobné C.LUI, výsledek je x2, konstanta je však násobena 16ti |
11 | C.SLLI | bitový posun registru rd/rs1 doleva |
12 | C.NOP | rd/rs1=0, imm=0 |
Poznámky:
- U prvních tří instrukcí platí, že registr rd nesmí být x0 (to by změnilo operační kód instrukce, navíc nemá význam ukládat nic do registru s konstantní nulou).
- U instrukce C.LI nesmí být rd=x0
- U instrukce C.LUI nesmí být rd=x0 či x2
- Instrukce C.SLLI dokáže pracovat se všemi registry, ovšem instrukce pro posun doprava nikoli. Je tomu tak z toho důvodu, že posuny doleva jsou častější, proto dostaly v instrukčním souboru prioritu.
11. Formát instrukcí typu CCS (stack-relative store)
Tento instrukční formát je využit u specializovaných instrukcí, u nichž se pro určení bázové adresy implicitně používá registr x2. Pokud se tento registr využívá ve funkci ukazatele na vrchol zásobníkového rámce, mohou instrukce z této skupiny sloužit pro přístup k lokálním proměnným uloženým právě na zásobníkovém rámci:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |function| offset | rs2 | op | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Význam jednotlivých bitových polí:
# | Bitové pole | Význam |
---|---|---|
1 | function | kód prováděné operace |
2 | offset | konstanta použitá pro výpočet adresy na zásobníku |
3 | rs2 | zdrojový registr (libovolný, včetně x0!) |
4 | op | obsahuje kód C2 |
Tento formát může být podporovaný až pěti instrukcemi, v závislosti na schopnostech konkrétního čipu:
# | Instrukce | Popis |
---|---|---|
1 | C.SWSP | uložení obsahu registru rs2 (32bitového slova) na adresu x2+offset×4 |
2 | C.SDSP | uložení obsahu registru rs2 (64bitového slova) na adresu x2+offset×8 |
3 | C.SQSP | uložení obsahu registru rs2 (128bitového slova) na adresu x2+offset×16 |
4 | C.FSWSP | uložení obsahu FP registru rs2 (float) na adresu x2+offset×4 |
5 | C.FSDSP | uložení obsahu FP registru rs2 (double) na adresu x2+offset×8 |
12. Formát instrukcí typu CIW (WIDE IMMEDIATE)
Tento formát používá pouze jediná instrukce C.ADDI4SPN:
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+ |function| imm | rd | op | +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
Význam jednotlivých bitových polí:
# | Bitové pole | Význam |
---|---|---|
1 | function | kód prováděné operace |
2 | imm | konstanta |
3 | rd | cílový registr |
4 | op | obsahuje kód C0 |
Instrukce C.ADDI4SPN vypočte offset×4, přičte k němu obsah registru x2 a uloží výsledek do cílového registru.
13. Výsledky měření: zmenšení velikosti kódu použitím RVC
Podívejme se nyní na výsledky měření, konkrétně na to, jak se zmenšil 64bitový Linuxový kernel a které instrukce na zmenšení měly největší vliv (ve skutečnosti máme k dispozici více výsledků měření, ty se však týkaly především benchmarků, což není tak praktický příklad jako v případě kernelu):
Instrukce | % zmenšení |
---|---|
C.MV | 5,00 % |
C.LDSP | 4,44 % |
C.SDSP | 3,79 % |
C.LI | 2,86 % |
C.LD | 2,09 % |
C.J | 1,53 % |
C.BEQZ | 1,24 % |
C.JR | 1,05 % |
C.ADDI | 0,95 % |
C.ADD | 0,91 % |
Celkově: | 31,11 % (všechny instrukce) |
Osobně mi tyto výsledky přijdou být velmi zajímavé, protože se ukazuje, že ve statickém kódu se nejčastěji vyskytují instrukce pro přenosy dat (prvních pět řádků), teprve poté podmíněné a nepodmíněné skoky a v první desítce nalezneme pouze dvě ALU instrukce, a to sčítání!
Ovšem dynamické měření (tj. počet provedených) instrukcí nám dá zcela odlišné výsledky:
Instrukce | % zmenšení |
---|---|
C.BNEZ | 3,62 % |
C.LD | 3,29 % |
C.LI | 2,73 % |
C.ADD | 1,84 % |
C.MV | 1,37 % |
C.J | 1,35 % |
C.LDSP | 1,31 % |
C.ADDI | 1,26 % |
C.SDSP | 1,18 % |
C.SD | 1,13 % |
Celkově: | 26,11 % (všechny instrukce) |
Asi podle očekávání toto měření „vyhrála“ instrukce pro podmíněný skok, která je (logicky) součástí většiny smyček.
14. Odkazy na Internetu
- RISC-V Draft Sompressed ISA Version 1.9 Released
https://blog.riscv.org/2015/11/risc-v-draft-compressed-isa-version-1–9-released/ - RISC vs. CISC: the Post-RISC Era
http://archive.arstechnica.com/cpu/4q99/risc-cisc/rvc-1.html - Introduction to ARM Thumb
http://www.embedded.com/electronics-blogs/beginner-s-corner/4024632/Introduction-to-ARM-thumb - Code Size – a comprehensive comparison of microMIPS32 and Thumb code size using many Megabytes of customer code
https://community.arm.com/groups/processors/blog/2014/04/28/code-size-a-comprehensive-comparison-of-micromips32-and-thumb-code-size-using-many-megabytes-of-customer-code - MIPS MCUs Outrun ARM
http://www.linleygroup.com/newsletters/newsletter_detail.php?num=5117 - Improving Energy Efficiency and Reducing Code Size with RISC-V Compressed
http://www.eecs.berkeley.edu/~waterman/papers/ms-thesis.pdf - An Introduction to Lock-Free Programming
http://preshing.com/20120612/an-introduction-to-lock-free-programming/ - Sequential consistency
https://en.wikipedia.org/wiki/Sequential_consistency - Understanding Atomic Operations
https://jfdube.wordpress.com/2011/11/30/understanding-atomic-operations/ - Load-link/store-conditional
https://en.wikipedia.org/wiki/Load-link/store-conditional - The RISC-V Compressed Instruction Set Manual (Pozor: verze 1.7)
http://riscv.org/spec/riscv-compressed-spec-v1.7.pdf - Carry bits, The Architect's Trap
http://yarchive.net/comp/carry_bit.html - Microprocessor Design/ALU Flags
https://en.wikibooks.org/wiki/Microprocessor_Design/ALU_Flags - Flags register in an out-of-order processor
http://cs.stackexchange.com/questions/42095/flags-register-in-an-out-of-order-processor - AMD Am29000
https://en.wikipedia.org/wiki/AMD_Am29000 - Status register
https://en.wikipedia.org/wiki/Status_register - AMD Am29000 microprocessor family
http://www.cpu-world.com/CPUs/29000/ - AMD 29k (Streamlined Instruction Processor) ID Guide
http://www.cpushack.com/Am29k.html - AMD Am29000 (Wikipedia)
http://en.wikipedia.org/wiki/AMD_Am29000 - AMD K5 („K5“ / „5k86“)
http://www.pcguide.com/ref/cpu/fam/g5K5-c.html - 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 tohoto 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 tomto projektu
https://iis.ee.ethz.ch/~gmichi/asocd/lecturenotes/Lecture6.pdf - Maska mikroprocesoru RISC 1
http://www.cs.berkeley.edu/~pattrsn/Arch/RISC1.jpg - Maska mikroprocesoru RISC 2
http://www.cs.berkeley.edu/~pattrsn/Arch/RISC2.jpg - C.E. Sequin and D.A.Patterson: Design and Implementation of RISC I
http://www.eecs.berkeley.edu/Pubs/TechRpts/1982/CSD-82–106.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 - SPARC Processor Family Photo
http://thenetworkisthecomputer.com/site/?p=243 - SPARC: Decades of Continuous Technical Innovation
http://blogs.oracle.com/ontherecord/entry/sparc_decades_of_continuous_technical - The SPARC processors
http://www.top500.org/2007_overview_recent_supercomputers/sparc_processors - Reduced instruction set computing (Wikipedia)
http://en.wikipedia.org/wiki/Reduced_instruction_set_computer - MIPS architecture (Wikipedia)
http://en.wikipedia.org/wiki/MIPS_architecture - Very long instruction word (Wikipedia)
http://en.wikipedia.org/wiki/Very_long_instruction_word - Classic RISC pipeline (Wikipedia)
http://en.wikipedia.org/wiki/Classic_RISC_pipeline - R2000 Microprocessor (Wikipedia)
http://en.wikipedia.org/wiki/R2000_(microprocessor) - R3000 Microprocessor (Wikipedia)
http://en.wikipedia.org/wiki/R3000 - R4400 Microprocessor (Wikipedia)
http://en.wikipedia.org/wiki/R4400 - R8000 Microprocessor (Wikipedia)
http://en.wikipedia.org/wiki/R8000 - R10000 Microprocessor (Wikipedia)
http://en.wikipedia.org/wiki/R10000 - SPARC (Wikipedia)
http://en.wikipedia.org/wiki/Sparc - CPU design (Wikipedia)
http://en.wikipedia.org/wiki/CPU_design - Control unit (Wikipedia)
http://en.wikipedia.org/wiki/Control_unit