Az utasításkészlet, vagy utasításkészlet-architektúra (Instruction Set Architecture, ISA) a számítógép-architektúra programozáshoz kötődő része, ami magába foglalja a bitszélességet, a használható natív adattípusokat, gépi kódú utasításokat, regisztereket, címzési módokat, memóriaarchitektúrát, megszakítás- és kivételkezelést és a külső I/O-t. Az ISA specifikációjához tartoznak az opkódok (a gépi kód) és az adott processzor natív parancsai.
Az utasításkészlet-architektúra különbözik a mikroarchitektúrától, ami az utasításkészletet megvalósító processzortervezési technikák összessége. Nagyon különböző mikroarchitektúrájú számítógépeknek is megegyezhet az utasításkészletük. Például az Intel Pentium és az AMD Athlon az x86 utasításkészlet csaknem azonos változatát valósítja meg, de radikálisan különböző belső felépítéssel.
Egyes virtuális gépek utasításkészlete támogatja a Smalltalk, Java virtuális gép vagy a Microsoft Common Language Runtime-jának a bájtkódját oly módon, hogy a gyakrabban végrehajtott kódrészleteket natív gépi kódra fordítják, a kevésbé gyakoriakat pedig interpretálva futtatják (lásd Just-in-time compilation). A Transmeta hasonlóan valósította meg az x86 utasításkészlet futtatását VLIW processzorokon.
Utasításkészletek osztályozása
Az utasításkészletek osztályozhatók: típus szerint (CISC, RISC, VLIW, EPIC) bitszélesség szerint (jellemzően 8 bit, 16 bit, 32 bit, 64 bit) regiszterek típusa és száma szerint címzési módok szerint operandusok száma szerint aszerint, hogy egy vagy több utasítás egy vagy több adaton végez-e műveletet (Flynn-féle osztályozás) egyéb szempontok lehetnek: van-e verem, megszakításkezelés, kivételkezelés, támogatott-e a hardveres virtualizáció stb.
A komplex utasításkészlettel rendelkező számítógépek (CISC) sok olyan, specializált utasítással bírnak, melyeket a programok csak ritkán használnak. A csökkentett utasításkészletű számítógépeket (RISC) úgy egyszerűsítették le, hogy csak azokat az utasításokat valósították meg bennük, melyek gyakran előfordulnak a programokban; a ritkább műveleteket szubrutinokkal oldják meg, a ritkán használt utasítások nagyobb futási idejét pedig ellensúlyozza az egyszerűbb felépítés. Elméleti fontosságú még a minimális utasításkészletű számítógép (MISC) és az egyutasításos számítógép; ilyenek kereskedelmi forgalomba nem kerültek. További variációk a nagyon hosszú utasításszavú (VLIW) architektúrák, ahol a processzor számos utasítása van egyetlen hosszú utasításszóba belekódolva, és a VLIW utódjának tekintett utasításkészlet nélküli számítástechnika (NISC).
Gépi kód A gépi kód vagy gépi nyelv diszkrét állításokból vagy utasításokból épül fel. Egy-egy gépi nyelvű utasítás a feldolgozó architektúrán belül az elvégzendő feladaton túl kijelölhet: meghatározott regisztereket aritmetika, címzési vagy vezérlési funkciókhoz meghatározott memóriacímeket vagy offsetet (eltolást) az operandusok értelmezését meghatározó címzési módokat.
A bonyolultabb műveletek ezeknek az egyszerűbb elemek kombinációjaként építhetők fel. A gépi kódú utasítások egymás után hajtódnak végre, vagy ahogy a programlefolyás-vezérlő utasítások meghatározzák.
Utasításfajták Számos utasításkészletben megtalálhatók a következő alapvető műveletek:
Adatkezelő és memóriakezelő műveletek értékadás (set): egy regiszter feltöltése egy konstans értékkel mozgatás (move): adatmozgatás memóriacímről egy regiszterbe, vagy fordítva. Célja egy regiszter tartalmának vagy egy művelet eredményének eltárolása a memóriában, vagy a tárolt adat betöltése későbbi műveletvégzés céljából. írás és olvasás (I/O, read-write) hardvereszközökről; az adatoknak a gépbe történő bevitelét, kiírását, illetve a külső perifériák adatforgalmának vezérlését végzik Az aritmetikai-logikai egységet (ALU) vezérlő utasítások két regiszter értékének összeadása, kivonása, szorzása vagy elosztása (add, subtract, multiply, divide), az eredmény egy regiszterbe kerül, a státuszregiszter egy vagy több bitjének (flagjének) értékét potenciálisan megváltoztatva bitműveletek, két regiszter megfelelő bitjei között végzett logikai és, logikai vagy, vagy egy regiszter bitjein végzett negáció. két regiszter értékének összehasonlítása (compare); pl. annak vizsgálata, hogy az egyik értéke kisebb-e a másikénál, netán egyenlőek programlefolyás-vezérlő (vezérlésátadó) utasítások, melyekkel elérhető, hogy az utasítások végrehajtási sorrendje eltérjen azok tárolási sorrendjétől feltétel nélküli elágazás a program egy más címére és az ottani utasítások elvégzése feltételes elágazás egy másik memóriacímre, ha egy feltétel teljesül számított ugrás vagy indirekt elágazás egy másik címre, a következő utasítás címének (a visszatérési címnek) elmentésével (szubrutinhívás) A feldolgozó egység állapotát befolyásoló utasítások a processzor speciális regisztereit módosítják, oly módon, hogy a folyamat további értelmezésére hatnak, például újraindítják vagy elaltatják a processzort, védett módba kapcsolják a feldolgozást stb. Egyéb utasítások, például várakozás vagy NOP (No OPeration), azaz üres utasítás.
Komplex utasítások Egyes platformok utasításkészlete „komplex” utasításokat is tartalmaz. Egyetlen komplex utasítás elvégzi, ami más számítógépeken sok normál utasítás feladata lenne. Az ilyen utasítások jellemzői, hogy több lépésben hajtódnak végre, számos végrehajtó egységet foglalkoztatnak vagy más módon nagyobb léptékűek az ugyanazon a processzoron futó egyszerű utasításoknál. Néhány példa komplex utasításokra:
egyszerre több regiszter mentése a verembe nagy memóriablokkok mozgatása bonyolult és/vagy lebegőpontos aritmetikai műveletek (szögfüggvények, négyzetgyökvonás stb.) atomi test-and-set utasítás (memóriába írás és a korábbi érték visszaadása egy műveletben) utasítások, amik az ALU értékét egy memóriából vett operandussal kombinálják (regiszterérték helyett)
Mostanában népszerű komplex utasításfajták a SIMD-, azaz Single-Instruction Stream Multiple-Data Stream (egy utasításfolyam, több adatfolyam), illetve vektorműveletek, melyek ugyanazt az aritmetikai műveletet végzik el egy időben nagy mennyiségű adaton. A SIMD segítségével lehetséges nagy vektorok vagy mátrixok manipulációja rövid idő alatt. A SIMD utasítások a hang-, kép- és videofeldolgozásban alkalmazott algoritmusok könnyű párhuzamosítását teszik lehetővé. Számos SIMD-implementáció jelent meg a piacon olyan kódneveken, mint MMX, 3DNow! vagy AltiVec.
Speciális célú processzorok, pl. GPU-k is tartalmaznak komplex utasításkészleteket. Mindazonáltal az ilyen egyedi processzorokhoz tartozó komplex utasításkészletek (és a natív assembly nyelv) gyakran nem hozzáférhetők publikusan a gyártói hardver zártságából fakadóan, így a szoftverfejlesztők szabványosított magasabb szintű nyelveken és API-kon keresztül programozhatják csak őket. Az OpenGL virtuális utasításkészlet és virtuális assembly nyelve (ARB assembly language) és a CUDA példázzák az ilyen, natív utasításkészlet fölött létrehozott hardverabsztrakciós rétegeket.
Egy utasítás részei bélyegkép|right|Egy utasítás több mezőt tartalmazhat, melyek azonosítják az elvégzendő logikai utasítást, ezen kívül tartalmazhatnak forrás- és/vagy célcímeket, konstans értékeket. A képen a MIPS „Add Immediate” utasítás látható, ami tartalmazhat forrás- és célregisztert és egy kis konstans értéket is.
A hagyományos architektúrák utasításai a következőkből épülnek föl: az elvégzendő utasítást meghatározó opkódból (pl. „add a memóriacím tartalmát egy regiszterhez”) és nulla vagy több operandusból (regiszterek, memóriacímek vagy konstans értékek). Az operandusoknak lehetnek az értelmezésüket meghatározó különböző címzési módjaik vagy fix mezőkön helyezkednek el.
A nagyon hosszú utasításhosszú (VLIW) architektúrákon, amik közé több mikrokód-architektúra tartozik, egyetlen utasítás több egyidejűleg végrehajtandó opkódot és azok operandusát tartalmazhatja.
Egyes egzotikus utasításkészletekben az opkód mező nem létezik (ilyen a Transport Triggered Architecture – TTA – és a Forth virtuális gép), csak operandus(oka)t. Más szokatlan, zéróoperandusú utasításkészletek nem tartalmaznak operandusmezőket, ilyen néhány veremgép, köztük a NOSC .
Utasításhossz Az utasítások hossza vagy mérete az architektúrák között széles tartományban változhat: egyes mikrokontrollerek négy bitjétől a VLIW rendszerek több száz bitjéig. A személyi számítógépek, mainframe-ek és szuperszámítógépek tipikus CPU-nak utasításhossza 8–64 bit között van. Az x86 architektúrában a leghosszabb lehetséges utasítás 15 bájtos (120 bites). Egy utasításkészleten belül az egyes utasítások különböző hosszúak is lehetnek. Bizonyos architektúrákon, jellemzően a legtöbb RISC gépen, az utasítások fix hosszúak, általában az adott architektúra szóhosszától függően. Más architektúrákon az utasítások különböző hosszúak lehetnek, tipikusan bájt vagy félszó többszörösei.
Megjelenítés Egy programot alkotó utasításokat ritkán adnak meg eredeti, numerikus formájukban. A programozók általában assembly nyelven adják meg őket, vagy még gyakrabban, fordítóprogram állítja elő őket.
Tervezés Az utasításkészletek tervezése komplex feladat. A mikroprocesszor fejlődésének két fontos állomása kapcsolódik ehhez. Az első a CISC (Complex Instruction Set Computer, komplex utasításkészletű számítógép), ami számos különböző utasítással rendelkezett. Az 1970-es években a mérnökök arra jutottak, hogy számos, ritkán használt utasítás egyszerűen elhagyható lenne. Az eredmény a RISC (Reduced Instruction Set Computer, csökkentett utasításkészletű számítógép) lett, egy kevesebb utasítást használó architektúra. Az egyszerűbb utasításkészlet előnye a magasabb elérhető órajel, csökkent processzorméret és energiafogyasztás. A komplexebb utasításkészlet ugyanakkor segítheti egyes utasítások optimalizálását, javíthatja a gyorsítótár hatékonyságát, egyszerűsítheti a programozást.
Egyes utasításkészletek fejlesztői fenntartottak egy vagy több opkódot egyfajta rendszerhívás vagy szoftvermegszakítás számára. Például a MOS Technology 6502 erre a 00H kódot, a Zilog Z80 a C7,CF,D7,DF,E7,EF,F7,FFHGanssle, Jack. "Proactive Debugging" . Published February 26, 2001. nyolcbájtos kódot, míg a Motorola 68000 az A000..AFFFH közötti kódokat használja erre a célra.
A gyors virtuális gépek megvalósítását nagyban támogatja, ha egy utasításkészlet megfelel a Popek- és Goldberg-féle virtualizációs követelményeknek.
A zavartűrő programozásban (Immunity Aware Programming) is használt NOP-csúszdák megvalósítása egyszerűbb, ha a memória definiálatlan, „nem programozott” állapotát NOP utasításnak értelmezi a processzor.
Többprocesszoros rendszereken könnyebb megvalósítani nem blokkoló szinkronizációs algoritmusokat, ha az utasításkészlet támogat olyan jellegű kombinált utasításokat, mint a fetch-and-add, a load-link/store-conditional (LL/SC) vagy az atomi compare and swap.
Utasításkészlet-megvalósítások Egy adott utasításkészlet hardveres (mikroarchitekturális) megvalósítása sokféle formát ölthet. Ezek egymással binárisan kompatibilisek, de különböző kompromisszumokat képviselhetnek költség, teljesítmény, energiafelhasználás, méret stb. tekintetében.
Egy processzor mikroarchitektúrájának tervezésekor a mérnökök olyan (gyakran külön megtervezett) bedrótozott elektronikus áramköri blokkokat használnak fel, mint az összeadó, szorzó, számláló áramkörök, regiszterek, ALU-k stb. Valamiféle, a regiszterek közti adatmozgást leíró nyelv (register transfer language) segítségével modellezik az ISA utasításainak dekódolását és kibocsátását. Két fő módja van az utasításkészletet megvalósító vezérlőegység (Control Unit) implementálásának (bár a kettő között számos középút létezik): A korai számítógépek és néhány egyszerűbb RISC számítógép „bedrótozta” a teljes utasításdekódolást és -kibocsátást (és a mikroarchitektúra többi részét is).