Obsah
1. RISCová architektura PowerPC (pokračování)
2. Varianty skokových instrukcí
3. Operace s příznaky uloženými v registru CR (Condition Register)
4. Modul určený pro vykonávání celočíselných operací
5. Instrukce typu LOAD a STORE
6. Základní aritmetické operace
7. Instrukce určené pro násobení a dělení
8. Instrukce pro porovnání operandů
1. RISCová architektura PowerPC (pokračování)
V první části článku o RISCové architektuře PowerPC jsme se seznámili především s programátorským pohledem na tyto procesory. Kromě stručného popisu formátu instrukcí a univerzálních pracovních registrů jsme si popsali čtveřici registrů, které na této architektuře mají speciální význam. Jednalo se o Condition Register, Fixed-Point Exception Register, Link Register a Count Register. Podrobnější popis se týkal především Condition Registru, protože jeho struktura je navržena takovým způsobem, aby byl používán nejenom pro řízení běhu programů (rozeskoky, programové smyčky), ale i pro realizaci některých složitějších logických výrazů, což je téma, o kterém se zmíníme ve třetí kapitole. Dále jsme si řekli, jakým způsobem jsou realizovány instrukce podmíněného i nepodmíněného skoku v modulu nazvaném Branch Processor. Dnes si popíšeme funkce dalšího modulu, tj. konkrétně modulu určeného pro provádění aritmetických a logických operací s celočíselnými operandy.
2. Varianty skokových instrukcí
Vraťme se ještě na chvíli k instrukcím určeným pro provádění skoků. V prvním článku jsme si řekli, že skokové instrukce i některé další instrukce určené pro řízení běhu programu jsou vykonávány jednotkou nazvanou Branch Processor. Existuje poměrně velké množství různých variant skokových instrukcí, protože kromě nepodmíněných skoků lze použít skok vykonaný na základě hodnoty některého stavového registru – Condition Register CR, Link Register LR a Count Register CTR. Následuje výpis možných variant různých podmínek, které mohou být testovány a při jejichž splnění se skok provede (pro úplnost je na prvním řádku zapsán i nepodmíněný skok):
# | Provedená operace před testem | Testovaná podmínka |
---|---|---|
1 | × | × skok se provede vždy (branch always) |
2 | × | test, zda vybraný bit CR == 0 |
3 | × | test, zda vybraný bit CR == 1 |
4 | snížení hodnoty CTR o 1 | CTR==0 |
5 | snížení hodnoty CTR o 1 | CTR!=0 |
6 | snížení hodnoty CTR o 1 | CTR==0 a současně vybraný bit CR == 0 |
7 | snížení hodnoty CTR o 1 | CTR==0 a současně vybraný bit CR == 1 |
8 | snížení hodnoty CTR o 1 | CTR!=0 a současně vybraný bit CR == 0 |
9 | snížení hodnoty CTR o 1 | CTR!=0 a současně vybraný bit CR == 1 |
Dále se (ortogonálně, tj. nezávisle na typu testu) může zvolit způsob výpočtu adresy skoku:
# | Adresa skoku |
---|---|
1 | absolutní |
2 | relativní vůči aktuální poloze v kódu |
3 | adresa je uložená v registru LR (Link Register) |
4 | adresa je uložená v registru CTR (Count Register) |
O dvou bitech, které mohou napomoci činnosti prediktoru skoků, jsme se již taktéž zmínili minule (zkráceně – pokud si je překladač jistý tím, že se nějaký skok velmi pravděpodobně provede či naopak velmi pravděpodobně neprovede, může nastavit příslušné dva bity). Ovšem u skoků používajících adresu uloženou v registru LR nebo CTR se navíc používá další poněkud odlišně koncipované bitové pole (opět o velikosti dvou bitů), které blíže tyto skoky popisuje:
Kombinace bitů | Cíl je v LR | Cíl je v CTR |
---|---|---|
00 | návrat ze subrutiny | velmi pravděpodobně se použije stejná adresa, jako v minulém skoku |
01 | nejedná se o návrat ze subrutiny | rezervováno |
10 | rezervováno | rezervováno |
11 | skok nelze staticky predikovat | skok nelze staticky predikovat |
Poznámka: tyto nápovědy pro prediktor skoků se mohou kombinovat s dvojicí bitů popsaných minule, takže lze například zkonstruovat skok typu „velmi nepravděpodobný návrat ze subrutiny na adresu uloženou v registru LR, který se provede za předpokladu, že registr CTR je po svém snížení o jedničku nulový“.
3. Operace s příznaky uloženými v registru CR (Condition Register)
Registr CR (Condition Register) jsme si již popsali minule, takže si dnes pouze ve stručnosti připomeňme, že tento 32bitový registr je rozdělen do osmi čtyřbitových polí označovaných symboly CR0 až CR7, přičemž pole CR0 má speciální význam, neboť jeho první tři bity v něm jsou nastavovány běžnými celočíselnými instrukcemi (sčítání atd.) a to konkrétně porovnáním výsledku operace s nulou. I druhé pole se jménem CR1, tj. bity 4 až 7 z příznakového registru CR, má speciální význam, neboť bity v něm jsou nastavovány při operacích s hodnotami s plovoucí řádovou čárkou.
Kromě skokových operací, které mohou testovat hodnotu libovolného bitu registru CR existuje na architektuře PowerPC i sada instrukcí určených pro vzájemné kombinace hodnot vybraných bitů tohoto registru. Tím je (alespoň teoreticky) umožněna snadná realizace některých podmínek zapsaných v některém vyšším programovacím jazyce. Tyto instrukce navíc trošku připomínají Booleovský procesor známý například z platformy Intel 8051:
# | Instrukce | Význam |
---|---|---|
1 | crand | bitová operace AND (logický součin) |
2 | cror | bitová operace OR (logický součet) |
3 | crxor | bitová operace XOR (nonekvivalence) |
4 | crnand | bitová operace NAND (negace logického součinu) |
5 | crnor | bitová operace NOR (negace logického součtu) |
6 | creqv | bitová operace EQV (ekvivalence) |
7 | crandc | bitová operace AND s prvním bitem a negací druhého bitu |
8 | crorc | bitová operace OR s prvním bitem a negací druhého bitu |
Všechny tyto instrukce ve svém instrukčním slově obsahují trojici pětibitových adres BA, BB a BT. Díky tomu je možné operaci provést s libovolnými dvěma bity registru CR a uložit výsledek opět do libovolného bitu tohoto registru (25=32).
4. Modul určený pro vykonávání celočíselných operací
Druhým modulem, z nichž se skládají procesory typu PowerPC, je modul určený pro vykonávání celočíselných operací. V originální dokumentaci se sice tento modul nazývá Fixed-Point Processor, ovšem ve skutečnosti se jedná o běžnou RISCovou aritmeticko-logickou jednotku. Pro celočíselné operace je možné jako operandy použít sadu třiceti dvou pracovních registrů nazvaných GPR0 až GPR31 (General-Purpose Registers), z nichž každý má šířku 64bitů (stále se bavíme o 64bitovém režimu PowerPC). Tato sada pracovních registrů je doplněna již výše zmíněným registrem nazvaným XER (Fixed-Point Exception Register) obsahujícím bitové příznaky nastavované při většině aritmetických operací. Některé další příznaky se pak ukládají do druhého stavového registru CR (Condition Register), jehož bity lze testovat s využitím výše zmíněných instrukcí pro podmíněný skok a upravovat s využitím logických operací.
5. Instrukce typu LOAD a STORE
Na architektuře PowerPC samozřejmě, jako ostatně na všech dalších RISCových architekturách, nalezneme instrukce určené pro načítání operandů z operační paměti i pro uložení výsledků operací zpět do operační paměti. Programátoři a autoři překladačů mají k dispozici poměrně velké množství variant instrukcí typu LOAD a STORE, přičemž jednotlivé varianty se od sebe odlišují adresními režimy i šířkou načítaných/ukládaných operandů. Adresa, resp. přesněji řečeno efektivní adresa, může být vypočítána mnoha různými způsoby, většinou se ale jedná o kombinaci obsahu některého pracovního registru (GPR) s šestnáctibitovou konstantou, která je přímo součástí instrukčního slova. U některých instrukcí má navíc speciální význam nulový index registru – v tomto případě se použije odlišný adresní režim.
Načítat je možné jednotlivé bajty, šestnáctibitová slova, 32bitová slova i 64bitová slova. Typ načítaného operandu se jednoduše pozná podle druhého písmene v mnemotechnické zkratce instrukce – lb?? značí načtení bajtu, lh?? načtení šestnáctibitového slova, lw?? načtení 32bitového slova a konečně ld? načtení slova 64bitového. Třetí písmeno v instrukci může označovat, jaká se provede konverze při rozšiřování načtených dat do plné šířky 64 bitů. To například znamená, že lhz? znamená instrukci pro načtení 16bitového slova s rozšířením na 64bitů tak, že se horních 48 bitů jednoduše vynuluje, zatímco instrukce lha? značí rozšíření znaménka (sign extension, v newspeaku PowerPC však algebraic extension).
Další jeden až dva znaky ve jménu instrukce pak označuje konkrétní typ výpočtu efektivní adresy: registr+16bitová konstanta, registr+registr atd. Navíc je možné, aby se výsledná adresa automaticky uložila zpět do registru použitého pro adresování (update – poslední znak instrukce bude u). Tuto vlastnost lze použít mnoha způsoby, například díky adresování registr+16bitová konstanta pro procházení polem prvek po prvku.
Podporovány jsou i speciální režimy při načítání a ukládání, například změna pořadí bajtů či blokové načítání/ukládání do většího množství registrů.
6. Základní aritmetické operace
Mezi základní aritmetické operace samozřejmě patří sčítání a odčítání. Na mikroprocesorech s architekturou PowerPC mají programátoři používající tyto instrukce poměrně velkou flexibilitu při výběru operandů, protože některé formy instrukcí obsahují ve svém slovu 16bitovou konstantu, kterou lze použít jako jeden vstupní operand. Mimochodem – právě tato technika se používá pro načtení konstanty do některého pracovního registru, protože například operace addi Rx, 0, hodnota je ekvivalentní instrukci li Rx, hodnota (addi značí Add Immediate a li pak Load Immediate). Podobných aliasů instrukcí nalezneme na architektuře PowerPC celou řadu. Podívejme se, které základní aritmetické instrukce typu „součet“ jsou podporovány (ve skutečnosti jsou možné i další kombinace):
# | Instrukce | Význam |
---|---|---|
1 | add | Rd=Rs1+Rs2 (nejběžnější forma nenastavující příznaky) |
2 | add. | Rd=Rs1+Rs2 (nastavuje bity v CR0) |
3 | addo | Rd=Rs1+Rs2 (nastavuje bity SO a OV) |
4 | addo. | kombinace předchozích dvou instrukcí |
5 | addi | Rd=Rs+konstanta |
6 | addi | Rd=konstanta (Rs==0) |
7 | addis | Rd=Rs+(konstanta<<16) |
8 | addis | Rd=Rs+(konstanta<<16) (Rs==0) |
9 | addc | add + nastavení bitu CA (příznak přenosu) |
10 | addic | addi + nastavení bitu CA (příznak přenosu) |
10 | adde | Rd=Rs1+Rs2+CA |
11 | addze | Rd=CA (jen přičtení příznaku přenosu) |
Poznámka: suffixy . a o jsou uvedeny jen u první instrukce add, ale lze je ve skutečnosti použít i u dalších instrukcí pro určení toho, které příznakové bity se mají nastavit.
7. Instrukce určené pro násobení a dělení
Procesory PowerPC obsahují i násobičku a děličku (přesněji řečeno specifikace popisuje násobičku a děličku, ovšem záleží pouze na konkrétní implementaci, zda budou tyto operace prováděny hardwarově či nějakou formou mikroinstrukcí). Čtenáře předchozích kapitol pravděpodobně nepřekvapí, že i v tomto případě mají instrukce velkou flexibilitu, a to jak co se týče velikosti operandů, tak i způsobu nastavování příznakových bitů. Násobit je možné jak dva registry, tak i vybraný pracovní registr a 16bitovou konstantu, která je součástí instrukčního slova. Totéž samozřejmě platí i pro instrukce určené pro děličku, ostatně podívejme se na následující dvě tabulky.
Nejprve je uvedena tabulka s instrukcemi pro násobení dvou operandů:
# | Instrukce | Význam |
---|---|---|
1 | mulli | násobení 64×64=64 Rd=Rs*konstanta (uloží se jen spodních 64 bitů výsledku) |
2 | mulld | násobení 64×64=64 Rd=Rs1*Rs2 (uloží se jen spodních 64 bitů výsledku) |
3 | mullw | násobení 32×32=64 Rd=Rs1*Rs2 (vstupem je dolní polovina 64bitových registrů) |
4 | mulhd | jako mulli, ale uloží se horních 64 bitů výsledku |
5 | mulhw | jako mulld, ale pouze horních 32 bitů 64bitového výsledku se uloží do Rd |
6 | mulhdu | jako mulli, ale uloží se horních 64 bitů výsledku, násobení čísel bez znaménka |
7 | mulhwu | jako mulhw, ale opět se jedná o násobení čísel bez znaménka |
Instrukce pro dělení:
# | Instrukce | Význam |
---|---|---|
1 | divd | dělení dvou 64bitových čísel (se znaménkem) |
2 | divw | dělení dvou 32bitových čísel |
3 | divdu | jako divd, ale pro čísla bez znaménka |
4 | divwu | jako diwv, ale pro čísla bez znaménka |
Poznámka: u těchto instrukcí lze použít suffix o popř. . pro určení, zda a jak se mají nastavovat příznakové bity. Je to velmi podobné kombinacím, o nichž jsme se zmínili u aritmetických instrukcí.
Poznámka 2: pro výpočet zbytku po dělení je nutné použít například následující sekvenci:
divd Rd, Rs1, Rs2 # podíl po celočíselném dělení mulld Rd, Rd, Rs2 # podíl po celočíselném dělení * dělitel subf Rd, Rd, Rs1 # zbytek po dělení
8. Instrukce pro porovnání operandů
Zajímavě jsou na architektuře PowerPC pojaty instrukce pro porovnání operandů. Na mnoha jiných typech mikroprocesorů jsou při porovnávání nastaveny příznakové bity ZF (příznak nulovosti), CF (příznak přenosu) a OF (příznak přetečení). U PowerPC je tomu jinak, protože je vždy nastaven pouze jeden ze tří bitů uložených do registru CR:
Bit v CR0 | Zkratka | Význam |
---|---|---|
0 | LT | Negative (kladný výsledek při porovnání/rozdílu) |
1 | GT | Positive (záporný výsledek při porovnání/rozdílu) |
2 | EQ | Zero (nulový výsledek při porovnání/rozdílu) |
Jak se s těmito bity pracuje již víme – buď se použijí při provedení podmíněného skoku nebo je možné tyto příznaky libovolným způsobem zkombinovat instrukcemi popsanými ve třetí kapitole (a poté je použít při podmíněném skoku).
Podporované instrukce pro porovnání operandů jsou zmíněny v tabulce:
# | Instrukce | Význam |
---|---|---|
1 | cmp | porovnání obsahu dvou pracovních registrů |
2 | cmpi | porovnání registru s 16bitovou konstantou |
3 | cmpl | porovnání 32bitových operandů chápaných jako hodnoty bez znaménka |
4 | cmpli | porovnání 32bitových operandů chápaných jako hodnoty bez znaménka |
Poznámka: v instrukčním slově lze zvolit, které bitové pole registru CR bude použito pro zápis příznaků.
9. Bitové rotace a posuny
Nejkomplikovanější jsou instrukce určené pro provádění bitových rotací a posunů. Tyto instrukce jsou velmi flexibilní, ovšem některé z nich mají ve svém 32bitovém instrukčním slovu zakódováno až pět operandů, protože kromě zdrojového a cílového registru je možné specifikovat masku, se kterou se po dokončení rotace provede bitové operace AND, tj. bitový součin. Podívejme se na příklad: instrukce s nevyslovitelným jménem rldicl má čtyři operandy:
- Zdrojový registr Rs
- Cílový registr Rd
- Počet míst, o které se bude rotovat
- Počáteční bit masky pro operaci AND (koncový bit je vždy shodný)
Naproti tomu instrukce rlwimi má pět operandů:
- Zdrojový registr Rs
- Cílový registr Rd
- Počet míst, o které se bude rotovat
- Počáteční bit masky pro operaci AND
- Koncový bit masky pro operaci AND
Maska je zkonstruována následovně: bity 64bitové masky ležící mezi počátečním a koncovým bitem jsou nastaveny na jedničku, ostatní bity jsou nulové. Pokud je však index počátečního bitu ostře větší, než index bitu koncového, je maska negována („uprostřed“ ní jsou nuly). Tyto operace jsou opět velmi flexibilní a v assembleru pro ně existuje několik jmenných aliasů. Příklad použití: dekódování složky RGB jedinou instrukcí.
10. Odkazy na Internetu
- Simplified PowerPC Instruction Set
http://www.ds.ewi.tudelft.nl/vakken/in101/labcourse/instruction-set/ - Assembly language for Power Architecture, Part 1: Programming concepts and beginning PowerPC instructions
http://www.ibm.com/developerworks/linux/library/l-powasm1/index.html - Assembly language for Power Architecture, Part 2: The art of loading and storing on PowerPC
http://www.ibm.com/developerworks/linux/library/l-powasm2/index.html - Assembly language for Power Architecture, Part 3: Programming with the PowerPC branch processor
http://www.ibm.com/developerworks/library/l-powasm3/index.html - Assembly language for Power Architecture, Part 4: Function calls and the PowerPC 64-bit ABI
http://www.ibm.com/developerworks/linux/library/l-powasm4/index.html - PowerPC overview (poněkud starší materiály z roku 2006)
http://titancity.com/articles/ppc.html - PowerPC (Wikipedia)
https://en.wikipedia.org/wiki/PowerPC - Status Register
https://en.wikipedia.org/wiki/Status_register - Why Learn Assembly Language?
http://www.codeproject.com/Articles/89460/Why-Learn-Assembly-Language - Is Assembly still relevant?
http://programmers.stackexchange.com/questions/95836/is-assembly-still-relevant - Why Learning Assembly Language Is Still a Good Idea
http://www.onlamp.com/pub/a/onlamp/2004/05/06/writegreatcode.html - Assembly language today
http://beust.com/weblog/2004/06/23/assembly-language-today/ - 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