Obsah
1. Architektura mikroprocesorů OpenRISC
2. Programátorský model OpenRISC
3. Funkce registrů při volání funkcí (dohodnutá konvence)
4. Registry se speciálními funkcemi
5. Nejdůležitější registry se speciální funkcí
6. Zjištění verze CPU, jeho architektury a dostupných jednotek
7. Přečtení konkrétních informací o možnostech nabízených mikroprocesorem
9. Instrukční sady použité v projektu OpenRISC
10. Formát slov v instrukční sadě ORBIS32
11. Instrukce v instrukční sadě ORBIS32
12. Aritmetické a logické instrukce
13. Příznakový bit F a instrukce pro práci s ním
14. Instrukce podmíněných i nepodmíněných skoků
17. Seznam všech instrukcí v sadě ORBIS32
1. Architektura mikroprocesorů OpenRISC
S projektem OpenRISC jsme se velmi stručně na stránkách Rootu již seznámili v článku Otevřené RISCové architektury OpenRISC a RISC-V . Od doby vydání tohoto článku již uplynula poměrně dlouhá doba (alespoň na poměry panující v IT) a navíc byl projekt OpenRISC prozatím popsán pouze povrchně, protože jsme se zaměřili spíše na „konkurenční“ jádra RISC V. Ovšem i OpenRISC se mezitím dále vyvinul a vznikly i jeho zajímavé alternativy, například šestnáctibitový procesor, který je na myšlenkách OpenRISCu založen. Proto se s touto zajímavou a potenciálně užitečnou mikroprocesorovou platformou znovu seznámíme v dnešním článku, který bude zaměřen především na popis architektury procesorů OpenRISC z programátorského hlediska. V navazujícím článku si navíc popíšeme referenční platformu nazvanou ORPSoC neboli OpenRISC Reference Platform System on Chip.
Připomeňme si, o jaký projekt se v případě OpenRISCu jedná. V rámci tohoto projektu byl především zveřejněn design procesoru, který byl uvolněn pod licencí LGPL. Případný firmware je pak k dispozici pod licencí GPL. To je – alespoň podle mého názoru – docela dobrý kompromis mezi zajištěním otevřenosti celé platformy a současně to umožňuje komerční využití, i když ne v takové míře, jako je tomu u RISC-V. Projekt počítá jak s možností implementace „pouhých“ 32bitových čipů, tak i čipů s 64bitovými sběrnicemi a aritmeticko-logickou jednotkou. Navíc je možné si při implementaci zvolit, zda bude mikroprocesor obsahovat i matematický koprocesor (pro hodnoty s plovoucí řádovou čárkou typu float/single, double či obojí), popř. je možné na čip s mikroprocesorem přidat i koprocesor určený pro zpracování hodnot uložených v krátkých vektorech (toto rozšíření se nazývá SIMD či DSP, protože v něm jsou obsaženy i některé typické instrukce používané při zpracování signálů).
2. Programátorský model OpenRISC
Popišme si nyní programátorský model mikroprocesorů OpenRISC. Podobně, jako tomu bylo u známé a stále používané architektury MIPS, i zde mají programátoři k dispozici šestnáct či (mnohem častěji) 32 pracovních registrů, každý o šířce 32 bitů popř. 64 bitů. Registry jsou pojmenované r0 až r15 (r31), což jsou opět jména v oblasti RISCů obvyklá. V následující tabulce jsou vypsány funkce jednotlivých pracovních registrů, ovšem s tou poznámkou, že tyto funkce jsou založeny pouze na konvenci (kromě prvního registru, který je při správné inicializaci CPU konstantně nulový, opět viz popis architektury MIPS):
Registr | Alternativní jméno | Význam |
---|---|---|
r0 | Zero | tento registr obsahuje konstantně nulu, díky němu lze do značné míry zjednodušit instrukční sadu |
r1 | SP | stack pointer, používá se jako ukazatel na vrchol zásobníku |
r2 | FP | frame pointer, používá se jako ukazatel na zásobníkový rámec |
r9 | LR | link register, používá se pro uchování návratové adresy volající subrutiny |
r11 | RV | return register, používá se pro předání návratové hodnoty do volající subrutiny |
r12 | RVH | return register, používá se pro předání návratové hodnoty do volající subrutiny |
Registry r11+r12 resp. RV+RVH se používají pro předání návratové hodnoty do volané funkce. Dvojice registrů je vyžadována například na 32bitových CPU v případě, že se má vracet typ long. Ovšem pozor – to, který z těchto registrů bude obsahovat vyšších 32 bitů a který nižších 32 bitů, záleží na tom, zda se jedná o CPU s pořadím bajtů little endian nebo big endian (alternativní jména těchto dvou registrů tedy mohou být poněkud matoucí).
3. Funkce registrů při volání funkcí (dohodnutá konvence)
Kromě šesti pracovních registrů, o nichž jsme se explicitně zmínili v předchozí kapitole, existuje dohodnutá (resp. přesněji řečeno specifikovaná) konvence pro funkci ostatních dvaceti šesti pracovních registrů. Tyto registry se obecně dělí do tří skupin:
- Registry použité pro předání parametrů volané funkci.
- Registry, u nichž je zaručeno, že se po návratu z volané funkce nezmění jejich obsah.
- Registry, které naopak po návratu z volané funkce mohou mít odlišnou hodnotu a volající funkce tedy musí s tímto chováním počítat.
Registry | Zachován při volání | Funkce |
---|---|---|
r3, r4, r5, r6, r7, r8 | ne | parametry předávané volané funkci |
r10, r14, r16, r18, r20, r22, r24, r26, r28, r30 | ano | registry, které se po návratu z funkce nezmění |
r13, r15, r17, r19, r21, r23, r25, r27, r29, r31 | ne | pracovní registry, mohou se změnit |
Tato konvence by měla být dodržována všemi dostupnými překladači.
4. Registry se speciálními funkcemi
Mimo obecných pracovních registrů, o nichž jsme se zmínili v předchozích dvou kapitolách, je ve specifikaci popsáno i několik desítek registrů se speciálními funkcemi. Tyto registry se souhrnně označují zkratkou SPR, která vznikla z jejich pojmenování special-purpose registers. Ne všechny dále popsané registry ovšem musí být implementovány všemi procesorovými jádry. Pokud některý registr není implementován (například se jedná o čip bez MMU, což je v případě MCU nebo DSP legitimní), musí být zaručeno, že čtení takového registru vrátí nulu a zápis do něj nebude mít žádný viditelný efekt (nejedná se ovšem ani o chybu ani o výjimku). Registry se speciálními funkcemi jsou rozděleny do skupin (groups), přičemž implementována by měla být alespoň nultá skupina, přesněji řečeno vybrané registry z této skupiny. To, které skupiny registrů jsou skutečně k dispozici, je určeno bitovým polem uloženým do speciálního registru nazvaného UPR:
Skupina | Význam |
---|---|
0 | stavové a řídicí registry |
1 | řízení MMU (memory management unit) pro data |
2 | řízení MMU (memory management unit) pro instrukce |
3 | vyrovnávací paměť pro data (stav a řízení) |
4 | vyrovnávací paměť pro instrukce (stav a řízení) |
5 | jednotka MAC popsaná dále |
6 | jednotka použitá pro ladění (debug) |
7 | čítače použité při měření výkonu, doby trvání instrukcí atd. |
8 | power management |
9 | řadič přerušení (PIC – Programmable Interrupt Controller) |
10 | časovače |
11 | registry používané matematickým koprocesorem |
12–23 | rezervováno, prozatím nepřiřazeno žádné funkci |
24–31 | skupiny registrů, které lze využít dalšími moduly na čipu (SoC apod.) |
Pro práci s těmito speciálními registry se používají dvě strojové instrukce:
# | Instrukce | Význam |
---|---|---|
1 | l.mtspr | zápis hodnoty z pracovního registru do registru se speciální funkcí |
2 | l.mfspr | přečtení hodnoty z registru speciální funkcí a zápis této hodnoty do pracovního registru |
5. Nejdůležitější registry se speciální funkcí
Index každého registru se speciální funkcí (SPR) je složen ze dvou částí. V bitech 11 až 15 je uloženo číslo skupiny (tj. hodnota 0..31) a v bitech 0 až 10 pak číslo registru v rámci skupiny. To mj. znamená, že v každé skupině může být definováno až 2048 registrů. Celkem je teoreticky možné použít 65536 registrů se speciální funkcí, ovšem této hodnoty samozřejmě prakticky nikdy nedosáhneme. V následující tabulce jsou popsány ty SPR registry, s nimiž se setká běžný programátor (pravda: používající assembler a OpenRISC – takže úplně běžný programátor to není). Vynechám asi sto registrů určených pro konfiguraci MMU, ladění, čítačů atd. I tyto registry jsou samozřejmě důležité a užitečné, ovšem ne při psaní aplikací běžících v uživatelském prostoru:
Skupina | Registr | Stručný popis | |
---|---|---|---|
0 | 0 | VR | obsahuje verzi (model) procesoru + číslo revize, používat by se měl VR2 a AVR |
0 | 1 | UPR | bitové pole popisující existující jednotky čipu |
0 | 1 | CPUCFGR | konfigurace CPU |
0 | 9 | VR2 | novější registr s verzí, nahrazuje funkci registru VR |
0 | 10 | AVR | verze architektury čipu, nahrazuje funkci registru VR |
0 | 12 | AECR | řízení obsluhy výjimek při aritmetických operacích |
0 | 13 | AESR | stav výjimek aritmetických operací |
0 | 16 | NPC | programový čítač (další hodnota PC) |
0 | 17 | SR | supervisor registr + příznaky ALU |
0 | 18 | PPC | programový čítač (předchozí hodnota PC) |
0 | 20 | FPCSR | řízení matematického koprocesoru, stav matematického koprocesoru |
5 | 1 | MACLO | použito jednotkou pro MAC, viz další text s popisem MACu |
5 | 2 | MACHI | použito jednotkou pro MAC, viz další text s popisem MACu |
Bit | Význam |
---|---|
0 | UPR je/není k dispozici |
1 | DCP – datová cache |
2 | ICP – instrukční cache |
3 | DPM – MMU pro data |
4 | IPM – MMU pro instrukce |
5 | MP – jednotka MAC |
6 | DUP – jednotka pro ladění |
7 | PCUP – jednotka s čítači |
8 | PICP – řadič přerušení PIC |
9 | PMP – jednotka pro řízení spotřeby |
10 | TTP – přesné čítače |
11–23 | rezervováno |
23–31 | CUP – custom unit/pro dále nespecifikované jednotky |
Hned nultý bit určuje, zda je vůbec UPR k dispozici. Připomeňme si, že při čtení jakéhokoli neexistujícího registru by se měla vrátit nula, takže i tento bit by byl nulový, čímž je potvrzeno, že GPR skutečně neexistuje.
6. Zjištění verze CPU, jeho architektury a dostupných jednotek
Vzhledem k tomu, že OpenRISC je navržen takovým způsobem, aby byl velmi flexibilní a rozšiřitelný, znamená to, že je nutné nějakým způsobem programátorům sdělit všechny důležité instrukce o konkrétním čipu, na nichž jejich program v daném okamžiku běží (tyto informace bude potřebovat loader jádra, samotné jádro a popř. obdoba BIOSu). K tomuto účelu původně sloužil registr nazvaný VR (Version Register), ovšem podle novější specifikace by se namísto tohoto registru měla použít dvojice registrů VR2 společně s registrem AVR. Oba zmíněné registry VR2+AVR jsou dostupné v režimu „supervisor“, tj. zejména pro loader jádra a taktéž pro samotné jádro (popř. i pro již zmíněnou obdobu BIOSu, pokud systém BIOS vyžaduje).
Obsah registru VR2:
Bity | Označení | Význam |
---|---|---|
31–24 | CPUID | unikátní číslo specifikující konkrétní čip |
23–0 | VER | postupně se zvyšující číslo verze čipu definovaného přes CPUID |
Obsah registru AVR:
Bity | Označení | Význam |
---|---|---|
31–24 | MAJ | verze architektury (majoritní číslo před tečkou) |
23–16 | MIN | verze architektury (minoritní číslo za tečkou) |
15–8 | REV | revize (číslo za druhou tečkou) |
7–0 | × | rezervováno |
Obsah tohoto registru by měl co nejpřesněji určit, které instrukce jsou implementovány a jaké je jejich přesné chování. Ovšem aby program nemusel používat složité tabulky, může namísto toho využít registr CPUCFGR popsaný v navazující kapitole.
7. Přečtení konkrétních informací o možnostech nabízených mikroprocesorem
Informace o konkrétních možnostech CPU, na kterém právě běží nějaký program, se zjistí přečtením registru nazvaného jednoduše CPUCFGR. V tomto 32bitovém registru je prozatím definováno celkem 15 bitů s následujícím významem:
Bity | Označení | Význam |
---|---|---|
0..3 | NSGF | počet tzv. stínových registrů GPR |
4 | CGF | velikost skupiny zákaznických GPR (méně nebo více než 32) |
5 | OB32S | podpora instrukční sady ORBIS32 (tu si popíšeme dnes) |
6 | OB64S | podpora instrukční sady ORBIS64 |
7 | OF32S | podpora instrukční sady ORFPX32 |
8 | OF64S | podpora instrukční sady ORFPX64 |
9 | OV64S | podpora instrukční sady ORVDX64 |
10 | ND | indikace, zda se při skocích používá branch delay slot či nikoli |
11 | AVRP | existence registru AVR popsaného výše |
12 | EVBARP | existence registru Exception Vector Base Address |
13 | ISRP | existence registrů implementačně závislých na daném CPU |
14 | AECSRP | existence registru Arithmetic Exception Control |
15..31 | × | rezervováno |
8. Příznakové bity
V kontextu programátorského modelu je důležitý především registr nazvaný SR (supervision register) patřící do nulté skupiny a mající index 17. Tento registr obsahuje mimo jiné i tyto tři jednobitové příznaky:
# | Zkratka | Příznak | Význam |
---|---|---|---|
1 | CY | carry | příznak přenosu při aritmetických operacích |
2 | OV | overflow | příznak přetečení při aritmetických operacích (typ signed) |
3 | F | flag/branch | příznak použitý pro implementaci podmíněných skoků |
Zajímavé je, že pro podmíněné skoky lze přímo využít jen příznak flag resp. branch. Ten je nastavován některou instrukcí pro porovnání dvou registrů, takže podmíněný skok je v praxi implementován vždy dvěma instrukcemi. Záleží hlavně na překladači, jak instrukce přeskládá, aby instrukce podmíněného skoku nemusela čekat na výsledek porovnání (připomeňme si, že dnešní čipy mají většinou pipeline se čtyřmi nebo s pěti řezy).
9. Instrukční sady použité v projektu OpenRISC
Vzhledem k tomu, že se předpokládá použití mikroprocesorových jader s architekturou OpenRISC v různých zařízeních, od jednodušších řídicích systémů (mikrořadiče – MCU) přes zpracování signálů (DSP) až například po servery, je instrukční sada OpenRISCu navržena modulárně. V současnosti existuje pět základních „sad“ instrukcí s předpokladem, že další sady bude možné navrhnout a implementovat v budoucnosti. Jediné, s čím se v architektuře OpenRISC přímo nepočítá (alespoň prozatím), je podpora instrukcí proměnné délky, tj. obdoby sad Thumb známých z konkurenční architektury ARM či podobné sady, kterou známe z RISC-V. V následující tabulce je vypsáno všech pět prozatím oficiálně popsaných sad instrukcí architektury OpenRISC:
# | Zkratka | Celé jméno | Stručný popis |
---|---|---|---|
1 | ORBIS32 | OpenRISC Basic Instruction Set | zpracování 32bitových operandů, skoky, podmínky, bitové operace |
2 | ORBIS64 | OpenRISC Basic Instruction Set | rozšíření na 64bitové operandy |
3 | ORFPX32 | OpenRISC Floating Point eXtension | operace s numerickými hodnotami typu float/single (jednoduchá přesnost) |
4 | ORFPX64 | OpenRISC Floating Point eXtension | operace s numerickými hodnotami typu double (dvojitá přesnost) |
5 | ORVDX64 | OpenRISC Vector/DSP eXtension | zpracování hodnot uložených v 64bitových vektorech |
Pro vytvoření reálně pracujícího mikroprocesoru postačuje implementovat pouze první sadu, tj. ORBIS32, samozřejmě s tím omezením, že zpracování 64bitových celých čísel či reálných čísel typu single a double bude prováděno softwarově (za pomoci subrutin). Základními vlastnostmi této instrukční sady se budeme zabývat v navazující kapitole.
10. Formát slov v instrukční sadě ORBIS32
Základní instrukční sada ORBIS32 se v několika ohledech podobá například instrukční sadě mikroprocesorů MIPS. I zde totiž najdeme instrukce s konstantní šířkou třiceti dvou bitů, které jsou v operační paměti vždy zarovnány na adresu dělitelnou čtyřmi. Díky tomu se u skoků nemusí specifikovat nejnižší dva bity adresy či offsetu, neboť tyto bity jsou vždy nulové. Tak, jako je tomu u MIPS, i zde mají instrukční slova tři formáty. První formát se označuje písmenem R a používá se pro většinu aritmetických, logických a porovnávacích operací prováděných se dvěma zdrojovými registry a jedním registrem cílovým. Další formát se jmenuje I a používá se pro instrukce, v nichž se pracuje se dvěma registry (zdrojový+cílový) a šestnáctibitovou konstantou. Třetí formát se jmenuje J a používá se u skoků, neboť součástí instrukčního slova je mj. i 26bitová konstanta (to postačuje, neboť nemusíme specifikovat spodní dva bity).
Formát R:
+-----+------+--------+--------+--------+------------------+ |31 30|29 26| 25 21 | 20 16 | 15 11 | 10 0 | +-----+------+--------+--------+--------+------------------+ |třída|opcode| rD (5) | rA (5) | rB (5) | druhá část opcode| +-----+------+--------+--------+--------+------------------+
Formát I:
+-----+------+--------+--------+---------------------------+ |31 30|29 26| 25 21 | 20 16 | 15 0 | +-----+------+--------+--------+---------------------------+ |třída|opcode| rD (5) | rA (5) | offset/konstanta (16) | +-----+------+--------+--------+---------------------------+
Formát J:
+-----+------+---------------------------------------------+ |31 30|29 26| 25 0 | +-----+------+---------------------------------------------+ |třída|opcode| adresa (26) | +-----+------+---------------------------------------------+
Pro porovnání si ukažme formáty instrukčních slov tak, jak jsou implementovány na klasickém 32bitovém MIPSu:
Formát R:
+------------+--------+--------+--------+-------+----------+ | 31 26 | 25 21 | 20 16 | 15 11 | 10 6 | 5 0 | +------------+--------+--------+--------+-------+----------+ | opcode (6) | rs (5) | rt (5) | rd (5) | shift | operace | +------------+--------+--------+--------+-------+----------+
Formát I:
+------------+-----------------+---------------------------+ | 31 26 | 25 21 | 20 16 | 15 0 | +------------+-----------------+---------------------------+ | opcode (6) | rs (5) | rt (5) | offset/konstanta (16) | +------------+-----------------+---------------------------+
Formát J:
+------------+---------------------------------------------+ | 31 26 | 25 0 | +------------+---------------------------------------------+ | opcode (6) | adresa (26) | +------------+---------------------------------------------+
11. Instrukce v instrukční sadě ORBIS32
Vzhledem k tomu, že všechny aritmetické a logické operace pracují s hodnotami uloženými v registrech, je množina instrukcí pro přesuny dat do a z paměti poměrně malá. OpenRISC podporuje instrukce typu load a store, které mohou zpracovávat bajty, 16bitová slova či 32bitová slova. Při načítání bajtů a 16bitových slov se provádí rozšíření na plných 32 bitů se znaménkem (doplnění podle nejvyššího bitu načítané hodnoty) či bez znaménka (doplnění nul). To je v mnoha ohledech praktické, neboť i ty nejmodernější 64bitové mikroprocesory mnohdy tráví většinu času zpracováním řetězců.
# | Instrukce | Význam |
---|---|---|
1 | l.extbs | znaménkové rozšíření bajtu na 32bitové slovo |
2 | l.extbz | bezznaménkové rozšíření bajtu na 32bitové slovo |
3 | l.exths | znaménkové rozšíření 16bitového slova na 32bitové slovo |
4 | l.exthz | bezznaménkové rozšíření 16bitového slova na 32bitové slovo |
5 | l.extws | pouhý přesun dat (32bit) nebo rozšíření 32bit na 64bit |
6 | l.extwz | pouhý přesun dat (32bit) nebo rozšíření 32bit na 64bit |
7 | l.lbs | načtení bajtu z operační paměti se znaménkovým rozšířením |
8 | l.lbz | načtení bajtu z operační paměti s bezznaménkovým rozšířením |
9 | l.lhs | načtení 16bitového slova se znaménkovým rozšířením |
10 | l.lhz | načtení 16bitového slova s bezznaménkovým rozšířením |
11 | l.ld | načtení dvouslova (jen 64bitová CPU) |
12 | l.lwa | atomické načtení slova |
13 | l.lws | načtení slova se znaménkovým rozšířením |
14 | l.lwz | načtení slova s bezznaménkovým rozšířením |
15 | l.movhi | načtení 16bitové konstanty a její uložení do horních 16bitů registru |
16 | l.sb | uložení bajtu |
17 | l.sh | uložení 16bitového slova |
18 | l.sw | uložení 32bitového slova |
19 | l.swa | atomické uložení 32bitového slova |
20 | l.sd | uložení dvouslova (jen 64bitová CPU) |
12. Aritmetické a logické instrukce
Mezi aritmetickými instrukcemi najdeme například sčítání s carry či bez carry, násobení a dělení (se znaménkem či bez znaménka), operace typu „multiply and accumulate“ a „multiply and subtract“ a dokonce instrukce ff1 (find first 1) a fl1 (find last 1). Už na tomto krátkém výčtu je patrné, že instrukční sada je poměrně rozsáhlá a implementace „na křemíku“ patřičně komplikovaná (měřeno plochou čipu).
Základní aritmetické instrukce:
# | Instrukce | Význam |
---|---|---|
1 | l.add | součet registrů |
2 | l.addc | součet (s dalším přičtením přenosu) |
3 | l.addi | přičtení konstanty |
4 | l.addic | přičtení konstanty (s dalším přičtením přenosu) |
5 | l.sub | |
6 | l.mul | násobení (se znaménkem) |
7 | l.mulu | násobení (bez znaménka) |
8 | l.muli | násobení konstantou (se znaménkem) |
9 | l.muld | násobení s přesunem výsledku do MAC |
10 | l.muldu | násobení s přesunem výsledku do MAC |
11 | l.div | celočíselné dělení (se znaménkem) |
12 | l.divu | celočíselné dělení (bez znaménka) |
13 | l.ff1 | nalezení první jedničky ve slově |
14 | l.fl1 | nalezení poslední jedničky ve slově |
Logické instrukce:
# | Instrukce | Význam |
---|---|---|
1 | l.and | logický součin bit po bitu |
2 | l.andi | logický součin registru s konstantou |
3 | l.or | logický součet bit po bitu |
4 | l.ori | logický součet registru s konstantou |
5 | l.xor | logická nonekvivalence bit po bitu |
6 | l.xori | logická nonekvivalence registru s konstantou |
Logické posuny a rotace:
# | Instrukce | Význam |
---|---|---|
1 | l.ror | rotace doprava |
2 | l.rori | rotace doprava o konstantu |
3 | l.sll | logický posun doleva |
4 | l.slli | logický posun doleva o konstantu |
5 | l.srl | logický posun doprava |
6 | l.srli | logický posun doprava o konstantu |
7 | l.sra | aritmetický posun doprava |
8 | l.srai | aritmetický posun doprava o konstantu |
13. Příznakový bit F a instrukce pro práci s ním
Za zmínku stojí taktéž instrukce začínající prefixem sf. Tyto instrukce nastavují příznakový bit branch/F na základě výsledku porovnání dvou registrů či porovnání registru s šestnáctibitovou konstantou. Hodnota příznakového bitu je následně využita v podmíněném skoku. Příkladem může být instrukce sfeq nastavující F←1 jen tehdy, pokud mají oba registry shodnou hodnotu. Nezapomeňme navíc na registr r0 s „trvalou nulou“, díky jehož existenci automaticky získáváme instrukce sfzero. Alternativou k sfeq je instrukce sfeqi pro porovnání registru s konstantou. Existují i další alternativy, kde se namísto „eq“ používá „gt“ (větší než), „ge“ (větší nebo rovno) atd.
# | Instrukce | Význam |
---|---|---|
1 | l.sfeq | nastavení F po porovnání dvou registrů na rovnost |
2 | l.sfeqi | nastavení F po porovnání registru s konstantou na rovnost |
3 | l.sfges | porovnání na relaci „větší nebo rovno“ (se znaménkem) |
4 | l.sfgesi | porovnání na relaci „větší nebo rovno“ (se znaménkem) |
5 | l.sfgeu | porovnání na relaci „větší nebo rovno“ (bez znaménka) |
6 | l.sfgeui | porovnání na relaci „větší nebo rovno“ (bez znaménka) |
7 | l.sfgts | porovnání na relaci „větší než“ (se znaménkem) |
8 | l.sfgtsi | porovnání na relaci „větší než“ (se znaménkem) |
9 | l.sfgtu | porovnání na relaci „větší než“ (bez znaménka) |
10 | l.sfgtui | porovnání na relaci „větší než“ (bez znaménka) |
11 | l.sfles | porovnání na relaci „menší nebo rovno“ (se znaménkem) |
12 | l.sflesi | porovnání na relaci „menší nebo rovno“ (se znaménkem) |
13 | l.sfleu | porovnání na relaci „menší nebo rovno“ (bez znaménka) |
14 | l.sfleui | porovnání na relaci „menší nebo rovno“ (bez znaménka) |
15 | l.sflts | porovnání na relaci „menší než“ (se znaménkem) |
16 | l.sfltsi | porovnání na relaci „menší než“ (se znaménkem) |
17 | l.sfltu | porovnání na relaci „menší než“ (bez znaménka) |
18 | l.sfltui | porovnání na relaci „menší než“ (bez znaménka) |
19 | l.sfne | nastavení F po porovnání dvou registrů na nerovnost |
20 | l.sfnei | nastavení F po porovnání registru s konstantou na nerovnost |
14. Instrukce podmíněných i nepodmíněných skoků
Formát skokových instrukcí jsme si již popsali, takže si jen připomeňme, že tyto instrukce používají 26bitovou adresu, která je buď absolutní nebo relativní. Podmíněné skoky využívají příznak F zmíněný ve třinácté kapitole. Mezi skokové instrukce patří zejména:
# | Instrukce | Význam |
---|---|---|
1 | l.j | běžný skok na adresu PC+konstanta |
2 | l.jal | skok na adresu PC+konstanta, návratová adresa se uloží do registru r9 |
3 | l.jr | skok na adresu uloženou ve specifikovaném registru |
4 | l.jalr | kombinace jal+jr (skok na adresu v registru, návratová adresa → r9) |
5 | l.bf | skok na PC+konstanta pokud je F nastaven |
6 | l.bnf | skok na PC+konstanta pokud je F vynulován |
7 | l.rfe | návrat z obsluhy výjimky |
Poslední instrukcí, o níž se v této kapitole zmíníme, je instrukce l.cmov používající taktéž tříadresový kód (indexy tří registrů). Tato instrukce může v některých případech nahradit podmíněné skoky:
- Pokud je F==1, proveď mov D,A
- Pokud je F==0, proveď mov D,B
15. Jednotka MAC
Čipy s architekturou OpenRISC mohou obsahovat i jednotku MAC provádějící operace označované stejně: MAC neboli Multiply-Accumulate. Jedná se o základní operace používané při zpracování signálů. Pokud je jednotka MAC skutečně implementována (zjistíme z registru UPR), bude k dispozici těchto šest specializovaných instrukcí:
# | Instrukce | Význam |
---|---|---|
1 | l.mac | operace MAC (se znaménkem) |
2 | l.macu | operace MAC (bez znaménka) |
3 | l.maci | operace MAC s konstantou |
3 | l.macrc | operace MAC s přenosem výsledku do pracovních registrů a vymazáním MAC registrů |
5 | l.msb | operace multiply-subtract (se znaménkem) |
6 | l.msbu | operace multiply-subtract (bez znaménka) |
Jednotka MAC používá vlastní dva registry nazvané MACHI a MACLO, do nichž se ukládají mezivýsledky. To je důležité, protože takto může MAC pracovat nezávisle na zbytku CPU a v průběhu výpočtu je tedy možné například vyhodnocovat adresy dalších operandů atd.
16. Branch delay sloty
Pro některé RISCové procesory (jmenujme například asi nejtypičtější MIPS, PA-RISC či SPARC) je poměrně obvyklé taktéž použití technologie takzvaných branch delay slotů, kterou můžeme najít i u zde popisovaných čipů s architekturou OpenRISC. Tyto čipy totiž mohou být navrženy tak, aby obsahovaly jeden delay slot, což znamená, že instrukce uložená ihned za instrukcí podmíněného či nepodmíněného skoku bude vykonána vždy, bez ohledu na výsledek skoku (zda se provede či neprovede). Díky existenci této technologie se může lépe využít instrukční pipeline, neboť pipeline není nutno celou vyprazdňovat po každém skoku, což znamená zdržení až čtyři takty v závislosti na konkrétních možnostech pipeline. Použití branch delay slotů je sice na první pohled poměrně jednoduché (ostatně většinu práce odvede překladač), ovšem může způsobit problémy ve chvíli, kdy dojde k výjimce v instrukci umístěné do delay slotu; navíc ještě záleží na tom, zda výjimka nastane už při dekódování instrukce nebo později. U OpenRISC lze existenci branch delay slotů zjistit přečtením bitu ND z registru CPUCFGR.
17. Seznam všech instrukcí v sadě ORBIS32
V následující tabulce jsou vypsány všechny instrukce, které jsou v současnosti součástí specifikace instrukční sady ORBIS32:
Instrukce | Instrukce | Instrukce | Instrukce | Instrukce |
---|---|---|---|---|
l.add | l.j | l.mtspr | l.sfgesi | l.sra |
l.addc | l.jal | l.msync | l.sfgeu | l.srai |
l.addi | l.jalr | l.mtspr | l.sfgeui | l.srl |
l.addic | l.jr | l.mul | l.sfgts | l.srli |
l.and | l.lbs | l.muld | l.sfgtsi | l.sub |
l.andi | l.lbz | l.muldu | l.sfgtu | l.sw |
l.bf | l.ld | l.muli | l.sfgtui | l.swa |
l.bnf | l.lhs | l.mulu | l.sfles | l.sys |
l.cmov | l.lhz | l.nop | l.sflesi | l.trap |
l.csync | l.lwa | l.or | l.sfleu | l.xor |
l.div | l.lws | l.ori | l.sfleui | l.xori |
l.divu | l.lwz | l.psync | l.sflts | |
l.extbs | l.mac | l.rfe | l.sfltsi | |
l.extbz | l.maci | l.ror | l.sfltu | |
l.exths | l.macrc | l.rori | l.sfltui | |
l.exthz | l.macu | l.sb | l.sfne | |
l.extws | l.mfspr | l.sd | l.sfnei | |
l.extwz | l.movhi | l.sfeq | l.sh | |
l.ff1 | l.msb | l.sfeqi | l.sll | |
l.fl1 | l.msbu | l.sfges | l.slli |
18. Obsah pokračování článku
V navazující části tohoto článku si popíšeme referenční architekturu nazvanou ORPSoC neboli OpenRISC Reference Platform System on Chip. Dále se zmíníme o dalších instrukčních sadách, zejména o instrukcích určených pro matematický koprocesor a pro DSP. Nezapomeneme ani na poměrně zajímavý projekt – menší 16bitový procesor založený na podobných principech jako OpenRISC.
19. Odkazy na Internetu
- OpenRISC (oficiální stránky)
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
https://iis.ee.ethz.ch/~gmichi/asocd/lecturenotes/Lecture6.pdf - OpenRISC System-on-Chip Design Emulation
https://arxiv.org/pdf/1602.03095.pdf - Open cores
https://opencores.org/ - Projekt OpenRISC 2000
https://opencores.org/project/or2k - OpenRISC na GitHubu
https://github.com/openrisc - OpenRISC 1200
https://en.wikipedia.org/wiki/OpenRISC_1200 - OpenRISC 1200 IP Core Specification (Preliminary Draft)
https://opencores.org/ocsvn/openrisc/openrisc/trunk/or1200/doc/openrisc1200_spec.pdf - 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) - 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 - CPUID na x86–64
http://www.felixcloutier.com/x86/CPUID.html - Endianness
https://en.wikipedia.org/wiki/Endianness - Otevřené RISCové architektury OpenRISC a RISC-V
https://www.root.cz/clanky/otevrene-riscove-architektury-openrisc-a-risc-v/ - Instrukční sada procesorových jader s otevřenou architekturou RISC-V
https://www.root.cz/clanky/instrukcni-sada-procesorovych-jader-s-otevrenou-architekturou-risc-v/ - Rozšíření instrukční sady procesorových jader s otevřenou architekturou RISC-V
https://www.root.cz/clanky/rozsireni-instrukcni-sady-procesorovych-jader-s-otevrenou-architekturou-risc-v/ - Instrukční sady procesorových jader s otevřenou architekturou RISC-V (dokončení)
https://www.root.cz/clanky/instrukcni-sady-procesorovych-jader-s-otevrenou-architekturou-risc-v-dokonceni/ - RISCové mikroprocesory s komprimovanými instrukčními sadami
https://www.root.cz/clanky/riscove-mikroprocesory-s-komprimovanymi-instrukcnimi-sadami/ - RISCové mikroprocesory s komprimovanými instrukčními sadami (2)
https://www.root.cz/clanky/riscove-mikroprocesory-s-komprimovanymi-instrukcnimi-sadami-2/