Architektura mikrořadičů s jádry ARM Cortex-M4

19. 1. 2016
Doba čtení: 21 minut

Sdílet

 Autor: Derrick Coetzee, podle licence: Public Domain CC0
Pátý článek o mikrořadičích založených na RISCových jádrech s architekturou ARM je věnován popisu řady Cortex-M4(F). Čipy obsahující tato jádra se podobají již dříve popsaným jádrům Cortex-M3, ovšem ve skutečnosti mají mnoho společného i s minule popsanými nejvýkonnějšími mikrořadiči Cortex-M7.

Obsah

1. Architektura mikrořadičů s jádry ARM Cortex-M4

2. Rozdíly mezi jádry Cortex-M

3. Segmenty trhu, pro něž jsou jednotlivá jádra Cortex-M určena

4. Nejdůležitější vlastnosti mikrořadičových jader Cortex-M4

5. Instrukční sada jader Cortex-M4

6. Základní instrukce

7. Instrukce orientované na zpracování signálu

8. Sčítání a odečítání se saturací

9. Bitový příznak Q

10. Násobička

11. Jádra Cortex-M4F

12. Operace podporované matematickým koprocesorem

13. Operace ze standardu IEEE 754, které nejsou implementovány

14. Odkazy na Internetu

1. Architektura mikrořadičů s jádry ARM Cortex-M4

V předchozí čtveřici článků o ARMovských (a tedy RISCových) mikrořadičových jádrech Cortex-M jsme si již popsali vlastnosti (v současnosti) nejmenších a energeticky nejméně náročných jader řady Cortex-M0 a Cortex-M0+ [1], základní vlastnosti výkonnějších jader Cortex-M3 [2], zabývali jsme se i nejvýkonnějšími jádry Cortex-M7 [3] a dokonce jsme si i popsali, v jakých aplikačních oblastech a čipech se tato mikroprocesorová jádra používají v praxi [4]. Jediná dvě „mikrořadičová“ jádra, kterými jsme se doposud podrobněji nezabývali, jsou jádra řady Cortex-M1, která dnes nachází uplatnění pouze v FPGA (a budeme se jimi zabývat v odlišně zaměřeném seriálu), a taktéž jádra řady Cortex-M4, jejichž možnosti leží na pomezí mezi řadou Cortex-M3 a Cortex-M7.

V dnešním článku tedy téma mikrořadičových RISCových jader Cortex-M uzavřeme, protože si popíšeme základní vlastnosti obvodů řady Cortex-M4 (jednodušší, levnější a energeticky méně náročná varianta) i jader Cortex-M4F (pod tímto označením nalezneme mikrořadičová jádra obsahující kromě celočíselné aritmeticko-logické jednotky i matematický koprocesor zpracovávající numerické údaje ve formátu single/float). Tato jádra se uplatní zejména v těch oblastech, kde se zpracovává číslicový signál, protože na čipech s jádry Cortex-M4 lze používat i instrukce pro sčítání a odčítání se saturací, je zde použita rychlá násobička a v případě potřeby lze zvolit mikrořadič obsahující již zmíněný matematický koprocesor.

2. Rozdíly mezi jádry Cortex-M

Vzhledem k tomu, že v tomto článku dokončíme popis všech typů procesorových (resp. přesněji řečeno mikrořadičových) jader Cortex-M, nebude na škodu si zopakovat, čím se vlastně jednotlivá „emková“ jádra od sebe odlišují. Zaměříme se především na vlastnosti samotných procesorových jednotek (CPU) a nikoli na vlastnosti periferních zařízení, protože je logické, že například minimalistická jádra Cortex-M0 a Cortex-M0+ budou v naprosté většině aplikací vybavena jen relativně malým množstvím podpůrných jednotek v porovnání s většími jádry Cortex-M7. V první tabulce jsou jednotlivá jádra všech řad Cortex-M rozdělena podle toho, do jaké architektury ARM spadají. Povšimněte si, že menší jádra používají starší, ale stále oblíbenou architekturu ARMv6-M, zatímco ta nejvýkonnější jádra přešla na novější architekturu ARMv7E-M. Na pomezí pak stojí minule popsaná jádra Cortex-M3 s architekturou ARMv7-M:

# Jádro (řada) Architektura ARM Architektura CPU/MCU
1 Cortex-M0 ARMv6-M Von Neumannova
2 Cortex-M0+ ARMv6-M Von Neumannova
3 Cortex-M1 ARMv6-M Von Neumannova
4 Cortex-M3 ARMv7-M Harvardská
5 Cortex-M4 ARMv7E-M Harvardská
6 Cortex-M7 ARMv7E-M Harvardská

Při pohledu na druhou tabulku se dozvíme, kolik řezů mají pipeline v jednotlivých jádrech a taktéž kolik vstupů přerušení je možné maximálně obsloužit. Na tomto místě stojí za připomenutí, že větší počet řezů v RISCových procesorech na jednu stranu může zvýšit jejich výpočetní výkon (zvětšení frekvence), na stranu druhou však zvětšuje plochu samotného CPU, reakce na přerušení se musí řešit složitějším způsobem (u některých čipů dosahuje latence reakce na přerušení až 12 cyklů) a taktéž se při špatné predikci skoků může zhoršit celkový výkon. U jader Cortex-M je patrné, že se designéři snažili o vybalancování všech veličin a vlastností (právě z tohoto důvodu se například dnes namísto papírově výkonnějších jader Cortex-M0 používají jádra Cortex-M0+ s jednodušší strukturou pipeline):

# Jádro Pipeline Přerušení
1 Cortex-M0 3 řezy 1–32 + NMI
2 Cortex-M0+ 2 řezy 1–32 + NMI
3 Cortex-M1 3 řezy 1–32 + NMI
4 Cortex-M3 3 řezy 1–240 + NMI
5 Cortex-M4 3 řezy 1–240 + NMI
6 Cortex-M7 6 řezů 1–240 + NMI

V poslední tabulce jsou shrnuty vlastnosti instrukčních sad, které si sice jsou v některých ohledech velmi podobné (například absencí původních 32bitových „RISCových“ instrukcí ARM), ovšem je patrné, že některé vlastnosti jsou dostupné až u větších, výkonnějších a nutno říci, že taktéž energeticky náročnějších jader:

# Jádro Instrukční sada HW násobička HW dělička Sat.ADD/SUB DSP FPU
1 Cortex-M0 Thumb 32bit ne ne ne ne
2 Cortex-M0+ Thumb 32bit ne ne ne ne
3 Cortex-M1 Thumb 32bit ne ne ne ne
4 Cortex-M3 Thumb+Thumb2 32/64bit ano ano ne ne
5 Cortex-M4 Thumb+Thumb2 32/64bit ano ano ano opt
6 Cortex-M7 Thumb+Thumb2 32/64bit ano ano ano opt

Poznámky k předchozí tabulce:

  • Jádra Cortex-M0/M0+/M1 obsahují většinu instrukcí Thumb kromě trojice instrukcí CBZ, CBNZ a prefixu IT. Taktéž obsahují šest vybraných instrukcí ze sady Thumb-2.
  • Ve sloupci „HW násobička“ je napsáno, zda je výsledek násobení dvou 32bitových čísel taktéž 32bitový (spodní polovina výsledku) či 64bitový. U některých čipů lze zvolit, zda je násobička sériová (pomalý výpočet, malá plocha čipu, malá spotřeba) či paralelní (rychlý výpočet, ovšem na úkor větší plochy čipy a taktéž vyšší spotřeby).

3. Segmenty trhu, pro něž jsou jednotlivá jádra Cortex-M určena

Typické použití mikrořadičových jader je zobrazeno na diagramu, který je dostupný na adrese http://www.arm.com/assets/i­mages/tpl/compare-Cortex-M-diagramLG.png. Zkusme si toto rozdělení shrnout v několika větách:

  1. Jádro Cortex-M0 tvoří základ pro čipy, u nichž je žádoucí dosáhnout co nejnižší výrobní ceny, malých rozměrů a především pak malého příkonu (s tím samozřejmě souvisí i příslušně nízký výpočetní výkon, ovšem možnost dlouhodobě provozovat stále relativně výkonný čip z baterie je jistě lákavá). Tato jádra by měla postupně nahrazovat některé aplikace, v nichž se nyní používají osmibitové či šestnáctibitové mikrořadiče (PIC, řada 8051, 68HC11/68HC12 atd.). Malé plochy čipu se inženýrům ze společnosti ARM skutečně podařilo dosáhnout, protože nejmenší vyráběný integrovaný obvod s jádrem Cortex-M0 má plochu přibližně 1,6×2 mm.
  2. Na mikrořadiče s jádry Cortex-M0+ se z pohledu programátora můžeme dívat jako na pouhá vylepšení původních jader Cortex-M0. Interně se ovšem jedná o odlišně navržená jádra, protože Cortex-M0+ obsahuje pipeline pouze se dvěma řezy a nikoli s řezy třemi (vlastně se tak vracíme na samotný začátek platformy ARM, což však u takto malých čipů má význam). Co je však pro případné uživatele důležitější – i díky zmenšenému počtu řezů pipeline se podařilo dále snížit spotřebu a přitom zachovat obousměrnou kompatibilitu s původními jádry Cortex-M0.
  3. Mezi základní cíl při návrhu jader Cortex-M3 patřilo vytvoření CPU s co nejmenší latencí, což znamená, že reakce na přerušení by měla proběhnout ideálně v jediném taktu. Navíc měly mít tyto procesory či mikrořadiče relativně dobrý výpočetní výkon, čehož bylo dosaženo hned několika způsoby. Především mají jádra Cortex-M3 Harvardskou architekturu umožňující mj. provádět současné čtení další instrukce společně se čtením či zápisem dat (zde ovšem závisí na konkrétním výrobci čipu, jak bude koncipovat interní sběrnice připojené k pamětem, samotné jádro rozdělení umožňuje). Dále je použita pipeline se třemi řezy (klasické RISCové fetch, decode, execute) a nalezneme zde i modul určený pro dopředné čtení instrukcí (PFU – Prefetch Unit) a další modul pro pozdržení zápisu jednoho slova do datové paměti (ovšem pouze pro ty regiony paměti, které jsou označeny příznakem „bufferable“, aby se zajistil okamžitý zápis do GPIO apod.).
  4. Mikrořadiče s jádry Cortex-M4 jsou popsány v navazující kapitole.
  5. Mikrořadičová jádra, která nesou označení Cortex-M7, jsou založena na architektuře ARMv7E-M, na rozdíl od čipů Cortex-M0/Cortex-M0+ s jednodušší architekturou ARMv6-M či Cortex-M3 s architekturou ARMv7-M. Tato jádra jsou podporována paměťovým subsystémem s cache i se zápisovým bufferem, používá se u nich matematický koprocesor, který může podporovat jak operace s operandy typu single/float, tak i s operandy typu double (což je v této aplikační oblasti poněkud neobvyklé) a podporovány jsou samozřejmě i operace používané při zpracování digitálního signálu, tj. například sčítání se saturací apod.

4. Nejdůležitější vlastnosti mikrořadičových jader Cortex-M4

Mikroprocesory a mikrořadiče s jádry Cortex-M4 jsou určeny pro ty aplikační oblasti, v nichž je vyžadováno zpracování digitálního signálu (může se jednat o osmibitové, šestnáctibitové či dokonce o 32bitové vzorky) popř. práce s daty uloženými v systému plovoucí řádové čárky (float/single). V těchto oblastech totiž již možnosti menších jader Cortex-M3 přestávají stačit a na druhou stranu jádra Cortex-M7 mohou být zbytečně drahá a/nebo mít zbytečně velké energetické nároky. Pokud je ovšem vyžadováno zpracování numerických hodnot typu double (tj. čísel s plovoucí řádovou čárkou s takzvanou dvojitou přesností), je nutné použít čipy s jádrem Cortex-M7 nebo se spokojit se softwarovou implementací všech operací s čísly typu double. Opět zde tedy můžeme vidět snahu o vybalancování vlastností se spotřebou a cenou.

Mezi další vlastnosti Cortex-M4 patří:

  • Podpora pro bit-banding, tj. pro přístup k jednotlivým bitům jednoho či dvou regionů paměti. Jedná se o vylepšenou podporu Booleovského procesoru známého z řady mikrořadičů Intel 8051 (které dnes vyrábí snad prakticky všichni významní výrobci polovodičových součástek kromě Intelu :-).
  • Volitelně je možné použít jednotku pro správu paměti (MPU – Memory Protection Unit). Paměť může být rozdělena do regionů s volitelnými právy přístupu (teoreticky tak lze realizovat i virtuální paměť, což však v aplikační oblasti Cortex-M4 asi nemá význam).
  • Lze použít i write buffer (pro jedno zapisované slovo), čímž se zajistí, že poslední řez pipeline nebude muset čekat na skutečný zápis dat do paměti.
  • Volitelně je k dispozici modul zajišťující použití konfigurovatelných watchpointů (watchpoint jde dokonce nastavit i na časovač či PC).
  • Hned několik volitelných modulů je určeno pro ladění: ITM (rozhraní pro připojení čipu k počítači, kde běží debugger), FPB (Flash path and Breakpoint unit) a AHB-AP (zajišťuje ladicím prostředkům přístup do operační paměti, k řídicím registrům a dokonce i k registrům samotného CPU).

5. Instrukční sada jader Cortex-M4

Základní instrukce zpracovávané jádry Cortex-M4 jsou shodné s čipy Cortex-M3Cortex-M7, protože je podporována jak instrukční sada Thumb s šestnáctibitovými operačními kódy, tak i instrukční sada Thumb-2, v níž kromě šestnáctibitových operačních kódů nalezneme i instrukce s 32bitovým slovem. Naproti tomu původní „čistě RISCová“ 32bitová instrukční sada ARM podporována není. Tato vlastnost však platí pro celou řadu Cortex-M, takže to pro nás pravděpodobně nebude příliš překvapivé. Ovšem v oblasti zpracování číslicových signálů je nutné, aby aritmeticko-logická jednotka podporovala kromě základních aritmetických instrukcí s 32bitovými operandy i další instrukce, zejména pak sčítání a odčítání se saturací či mnoho kombinací násobení dvou operandů. I tyto instrukce jádra Cortex-M4 dokážou zpracovat, o čemž se ostatně přesvědčíme v navazujících kapitolách.

6. Základní instrukce

Vzhledem k tomu, že instrukční sady Thumb a Thumb-2 jsou navrženy zejména s ohledem na dosažení vysoké hustoty výsledného strojového kódu a méně už s ohledem na eleganci či dokonce ortogonalitu, je instrukční sada v porovnání s původní RISCovou instrukční sadou (dnes pro odlišení nazývanou ARM32) značně odlišná; najdeme zde mnoho ad-hoc instrukcí i některé instrukce, které už nejsou čistě RISCové. To se týká zejména prefixu IT{podmínka} a taktéž instrukcí určených pro načtení či uložení většího množství registrů LDM a STM. Význam některých méně obvyklých instrukcí bude vysvětlen v poznámkách:

Prováděná operace Instrukce patřící do skupiny
Přesuny dat MOV, MNV, MOVW, MOVT, MRS, BSR
Konverze dat SXTB, SXTH, UXTB, UXTH
   
Součet (celočíselný) ADD, ADC, ADR
Rozdíl (celočíselný) SUB, SBC, RSB
Součin (celočíselný) MUL, MLA, MLS, SMULL, UMULL, SMLAL, UMLAL
Podíl (celočíselný) SDIV, UDIV
   
Porovnání a testy CMP, CMN, TST, TEQ, CLZ
Logické operace AND, ORR, ORN, EOR
Bitové operace BIC
Logické a aritmetické posuny LSL, LSR, ASR
Bitové rotace ROR, RRX
Posuny se saturací SSAT, USAT
Otočení bitů REV, REV16, REVSH, RBIT
Bitová pole UBFX, SBFX, BFC, BFI
   
Load (jeden registr) LDR, LDRH, LDRB, LDRSH, LDRSB, LDRT, LDRHT, LDRBT, LDRSHT, LDRSBT, LDRD
Load (více registrů) LDM
Store (jeden registr) STR, STRH, STRB, STRSH, STRSB, STRT, STRHT, STRBT, STRSHT, STRSBT, STRD
Store (více registrů) STM
   
Práce se zásobníkem PUSH, POP
Skoky B, BL, BX, BLX, TBB, TBH
Větvení B{podmínka}, CBZ, CBNZ
   
Události a přerušení SEV, WFE, WFI, CPSID, CPSIE
Práce s bariérami ISB, DMB, DSB
Práce se semafory LDREX, LDREXH, LDREXB, STREX, STREXH, STREXB, CLREX
   
Ostatní instrukce NOP, SVC, IT{podmínka}, BKPT

Poznámky:

  • Instrukce SVC se mj. používá pro volání služeb kernelu.
  • Instrukce SSAT a USAT se používají pro posun operandu s následnou saturací na zvolený počet bitů. SSAT provádí znaménkovou operaci, zatímco USAT provádí operaci bezznaménkovou.
  • Instrukce TBB (Table Branch Byte) a TBH (Table Branch Halfword) mohou být použity například při překladu aplikací napsaných ve vyšších programovacích jazycích, typicky céčka s jazykovou konstrukcí typu switch. Tyto instrukce jsme si již popsali v rámci článku o jádrech Cortex-M7.
  • Instrukce CBZ a CBNZ slouží k provedení skoku (rozvětvení), v případě, že je vybraný pracovní registr nulový či naopak nenulový (compare and branch if [not] zero).
  • Instrukční prefix IT{podmínka} může být aplikován na jednu až čtyři instrukce následující za prefixem. Ihned za prefixem IT se (bez mezery) udává, zda má být daná instrukce provedena při splnění podmínky (T – then) či naopak při jejím nesplnění (E – else). U první instrukce je automaticky předpokládáno T, tudíž se při práci v assembleru uvádí maximálně tři kombinace znaků T/E. Samozřejmě je taktéž nutné zapsat i testovanou podmínku – může se jednat o kódy používané jak u podmíněných skoků, tak i v podmínkových bitech.
  • Instrukce REV a REV16 otáčí pořadí bajtů ve 32bitovém či 16bitovém slovu (lze použít pro konverzi little-big endian atd.), zatímco instrukce RBIT otočí pořadí všech bitů ve 32bitovém slovu. To je docela užitečná operace, zejména v oblasti zpracování signálů.
  • U instrukcí LDM a STM je součástí instrukčního slova i bitové pole určující, které pracovní registry mají být načteny či naopak uloženy do operační paměti.

7. Instrukce orientované na zpracování signálu

Jak jsme si již řekli v předchozích kapitolách, jsou mikrořadičová jádra navržena takovým způsobem, aby je bylo možné efektivně použít při zpracování digitálních signálů. S tím samozřejmě souvisí i podpora pro některé specializované instrukce, o nichž se ve stručnosti zmíníme v následujících odstavcích. Mezi instrukce určené pro zpracování signálu patří především:

  1. Sčítání a odčítání se saturací.
  2. Instrukce MLA (Multiply and Accumulate) a MLS (Multiply and Subtract), kde především první instrukce je používaná například v číslicových filtrech.
  3. Varianty MLA s 64bitovým výsledkem, rozlišuje se znaménkové a bezznaménkové násobení atd. (viz násobička).
  4. Již výše zmíněné instrukce SSAT a USAT.
  5. Instrukce RBIT pro algoritmus výpočtu FFT apod.
  6. Instrukce pro konverze dat (protože mnoho vstupních číslicových dat používá osmibitové či šestnáctibitové vzorky).

8. Sčítání a odečítání se saturací

Kromě běžných aritmetických operací je možné u čipů s jádry Cortex-M4 použít i operace se saturací. Při využití těchto operací nedojde k přetečení přes maximální či minimální 8bitovou, 16bitovou či 32bitovou hodnotu (se znaménkem či bez znaménka), ale výpočet se „zasekne“ na minimální či maximální hodnotě.

# Instrukce Typ Šířka operandů Poznámka
1 SSAT Signed 32 bitů posun operandu před výpočtem
2 SSAT16 Signed 2×16 bitů posun operandu před výpočtem
3 USAT Unsigned 32 bitů posun operandu před výpočtem
4 USAT16 Unsigned 2×16 bitů posun operandu před výpočtem
5 QADD Signed 32 bitů součet se saturací
6 QADD8 Signed 4×8 bitů součet se saturací
7 QADD16 Signed 2×16 bitů součet se saturací
8 QSUB Signed 32 bitů rozdíl se saturací
9 QSUB8 Signed 4×8 bitů rozdíl se saturací
10 QSUB16 Signed 2×16 bitů rozdíl se saturací
11 QASX Signed 32 bitů add + exchange
12 QSAX Signed 32 bitů sub + exchange
13 QDADD Signed 32 bitů druhý operand je před výpočtem vynásoben dvěma
14 QDSUB Signed 32 bitů druhý operand je před výpočtem vynásoben dvěma
15 UQADD8 Unsigned 4×8 bitů součet se saturací
16 UQADD16 Unsigned 2×16 bitů součet se saturací
17 UQSUB8 Unsigned 4×8 bitů rozdíl se saturací
18 UQSUB16 Unsigned 2×16 bitů rozdíl se saturací
19 UQASX Unsigned 32 bitů add + exchange
20 UQSAX Unsigned 32 bitů add + exchange

9. Bitový příznak Q

Proč se vlastně ve jménech většiny instrukcí, které byly vypsány v předchozí tabulce, objevuje znak Q? Souvisí to s bitovým příznakem označeným (překvapivě) Q, který je taktéž nazýván sticky flag či sticky overflow bit (což není zcela přesné). Slovo „sticky“ se používá z toho důvodu, že pokud jednou dojde k jeho nastavení (na jedničku), musí se o jeho vynulování explicitně postarat programátor, na rozdíl od ostatních příznaků (Z, V, C apod.), které se mění s každou relevantní instrukcí. Příznak Q je nastaven ve chvíli, kdy při nějaké aritmetické operaci dojde k saturaci. To lze použít například k detekci špatně nastavených parametrů při zpracování signálu (příliš velké zesílení apod.). Díky tomu, že příznak Q není běžnými instrukcemi nulován, není nutné jeho nastavení testovat po každé aritmetické operaci, ale například až po zpracování celého bloku dat či po aplikaci celého filtru na jeden vzorek, což je rychlejší a většinou i dostačující.

10. Násobička

Násobička všech mikrořadičových jader Cortex-M4 podporuje takřka nepřeberné množství instrukcí pro násobení celočíselných operandů typu signed či unsigned (se znaménkem, bez znaménka) s tím, že výsledek je buď 32bitová hodnota či hodnota 64bitová. Navíc je možné určit, zda se má výsledek násobení přičíst k mezivýsledku a provést tak v oblasti digitálního zpracování signálů velmi užitečnou operaci nazývanou „Multiply&Accumulate“ (přičemž akumulátor má většinou šířku 32 bitů či 64 bitů, zatímco vstupní operand může být v některých instrukcích pouze šestnáctibitový). Následuje tabulka se základními operacemi násobičky:

# Instrukce Operandy Výsledek Počet cyklů Operace
1 MUL 32bit×32bit 32bit 1 násobení
2 MAL 32bit×32bit 32bit 2 násobení a přičtení výsledku (Multiply and Accumulate)
3 MLS 32bit×32bit 32bit 2 násobení a odečtení výsledku (Multiply and Subtract)
4 SMULL 32bit×32bit 64bit 1 násobení hodnot se znaménkem
5 SMLAL 32bit×32bit 64bit 1 Multiply and Accumulate (se znaménkem)
6 UMULL 32bit×32bit 64bit 1 násobení hodnot bez znaménka
7 UMLAL 32bit×32bit 64bit 1 Multiply and Accumulate (bez znaménka)
8 UMAAL 32bit×32bit+32+32 64bit 1 Multiply and Accumulate long (bez znaménka)
9 SMLAD 16bit×16bit 32bit 1 násobení dvouprvkových vektorů
10 SMLADX 16bit×16bit 32bit 1 násobení dvouprvkových vektorů

DSP operace (povšimněte si zejména konstantního počtu cyklů pro zahájení či dokončení operace):

# Instrukce Počet cyklů Operace
1 SMLALD 1 Signed Multiply Accumulate Long Dual (16bit×64bit)
2 SMLAWB 1 Signed Multiply Accumulate (word by halfword)
3 SMLAWT 1 Signed Multiply Accumulate (word by halfword)
4 SMLSD 1 Signed Multiply Subtract Dual
5 SMLSLD 1 Signed Multiply Subtract Long Dual
6 SMMLA 1 Signed Most Significant Word Multiply Accumulate
7 SMMLS 1 Signed Most Significant Word Multiply Subtract
8 SMUAD 1 Signed Dual Multiply Add
9 SMMUL 1 Signed Most Significant Word Multiply
10 SMULWB 1 Signed Multiply (word by halfword)
11 SMMLAR 1 32-bit multiply with rounded 32-most-significant-bit accumulate
12 SMMLSR 1 32-bit multiply with rounded 32-most-significant-bit subtract
13 SMMULR 1 32-bit multiply returning rounded 32-most-significant-bits
14 SMLABB 1 Q setting 16-bit signed multiply with 32-bit accumulate, bottom by bottom
15 SMLABT 1 Q setting 16-bit signed multiply with 32-bit accumulate, bottom by top
16 SMLALBB 1 16-bit signed multiply with 64-bit accumulate, bottom by bottom
17 SMLALBT 1 16-bit signed multiply with 64-bit accumulate, bottom by top
18 SMLALTB 1 16-bit signed multiply with 64-bit accumulate, top by bottom
19 SMLALTT 1 16-bit signed multiply with 64-bit accumulate, top by top
20 SMULBB 1 16-bit signed multiply yielding 32-bit result, bottom by bottom
21 SMULBT 1 16-bit signed multiply yielding 32-bit result, bottom by top
22 SMULTB 1 16-bit signed multiply yielding 32-bit result, top by bottom
23 SMULTT 1 16-bit signed multiply yielding 32-bit result, top by bottom
24 SMULWT 1 16-bit by 32-bit signed multiply returning 32-most-significant-bits, top
25 SMUSD 1 Dual 16-bit signed multiply returning difference
26 SMLATB 1 Q setting 16-bit signed multiply with 32-bit accumulate, top by bottom
27 SMLATT 1 Q setting 16-bit signed multiply with 32-bit accumulate, top by top

Neříkal někdo, že zkratka RISC je odvozena od „Reduced Instruction Set“? :-)

11. Jádra Cortex-M4F

Základní mikrořadičová jádra označovaná pouze jménem Cortex-M4 (tj. bez znaku „F“ na konci) neobsahují žádný matematický koprocesor, který by dokázal nativně pracovat s numerickými hodnotami s plovoucí řádovou čárkou. To je pochopitelné, protože existuje poměrně mnoho aplikací, v nichž si vystačíme pouze s operacemi nad celými čísly popř. s vlastní implementací výpočtů s fixní řádovou čárkou (FX, fixed point). Pokud je však v nějaké aplikaci většina výpočtů prováděna s numerickými hodnotami typu single/float, může být výhodnější namísto jádra Cortex-M4 použít jádro Cortex-M4F, které již matematický koprocesor obsahuje – ovšem s několika omezeními, na která je zapotřebí si dávat pozor, a to zejména při portaci aplikací. Jedno z největších omezení spočívá v tom, že matematický koprocesor skutečně podporuje pouze typ single/float a nikoli double (což v některých případech nemusí vadit, ostatně své použití mají i šestnáctibitové formáty s plovoucí řádovou čárkou).

Poznámka: ve skutečnosti je několik operací pro práci s dvojitou přesností přece jen implementováno, což uvidíme v tabulce v další kapitole.

Matematický koprocesor implementovaný v jádrech Cortex-M4F se v mnoha ohledech odlišuje například od „klasických“ koprocesorů řady 80×87 (v nichž výpočty interně probíhají s hodnotami rozšířenými na plných 80 bitů, což mj. dovoluje bezeztrátovou konverzi mezi celočíselnými hodnotami long a interně používaným formátem koprocesoru). Především se v RISCovém matematickém koprocesoru operandy ukládají do sady registrů označených jmény S0S31, na které existují aliasy D0D15 (vždy dva registry, které původně nesly informace o numerické hodnotě typu float/single jsou použity pro uložení hodnoty typu double). Dále je možné zvolit tři režimy činnosti koprocesoru, které mají vliv na prováděné výpočty: režim odpovídající normě IEEE 754 (Full-compliance mode), režim při kterém jsou denormalizované hodnoty považovány za nulu (Flush to zero mode) a konečně režim, při kterém všechny operace, u nichž je jeden či oba vstupní operandy roven NaN (Not a Number), taktéž vrací NaN (naopak v režimu kompatibility s normou IEEE 754 se hodnoty NaN zpracovávají podle specifikace).

ict ve školství 24

12. Operace podporované matematickým koprocesorem

Operace, které jsou podporovány matematickým koprocesorem, jsou vypsány v následující tabulce:

# Skupina Instrukce Počet cyklů Popis Prováděný výpočet
1 Aritmetické operace VADD.F32 Fd, Fn, Fm 1 součet Fd := Fn + Fm
2 Aritmetické operace VSUB.F32 Fd, Fn, Fm 1 rozdíl Fd := Fn – Fm
3 Aritmetické operace VNEG.F32 Fd, Fm 1 změna znaménka Fd := – Fm
4 Aritmetické operace VABS.F32 Fd, Fm 1 absolutní hodnota Fd := abs(Fm)
5 Aritmetické operace VSQRT.F32 Fd, Fm 14 druhá odmocnina Fd := sqrt(Fm)
6 Aritmetické operace VDIV.F32 Fd, Fn, Fm 14 dělení Fd := Fn / Fm
7 Aritmetické operace VMUL.F32 Fd, Fn, Fm 1 násobení Fd := Fn * Fm
8 Aritmetické operace VMLA.F32 Fd, Fn, Fm 3 násobení + akumulace Fd := Fd + (Fn * Fm)
9 Aritmetické operace VMLS.F32 Fd, Fn, Fm 3 odečtení součinu Fd := Fd – (Fn * Fm)
10 Aritmetické operace VNMUL.F32 Fd, Fn, Fm 1 násobení + změna znaménka Fn := – (Fn * Fm)
11 Aritmetické operace VNMLA.F32 Fd, Fn, Fm 3 kombinace VNMUL a VMLA Fd := – Fd – (Fn * Fm)
12 Aritmetické operace VNMLS.F32 Fd, Fn, Fm 3 kombinace VNMUL a VMLS Fd := – Fd + (Fn * Fm)
13 Aritmetické operace VFMA.F32 Fd, Fn, Fm 3 fused multiply and accumulate (jedno zaokrouhlení) Fd := Fd + (Fn * Fm)
14 Aritmetické operace VFMS.F32 Fd, Fn, Fm 3 dtto + odečtení součinu Fd := Fd – (Fn * Fm
15 Aritmetické operace VFNMA.F32 Fd, Fn, Fm 3 fused VNMLA Fd := – Fd – (Fn * Fm)
16 Aritmetické operace VFNMS.F32 Fd, Fn, Fm 3 fused VNMLS Fd := – Fd + (Fn * Fm)
17 Porovnání VCMP.F32 Fd, Fm 1 porovnání obsahu dvou registrů Fd – Fm
18 Porovnání VCMP Fd, #0.0 1 porovnání jednoho registru s nulou Fd – 0.0
19 Konverze VCVT.F32 1 konverze integer → single  
20 Přesuny dat VMOV Sn, Rd 1 přesun dat do registru koprocesoru Sn := Rd (Rd = registr ARM procesoru)
21 Přesuny dat VMOV Rd, Sn 1 přesun dat do registru CPU Rd := Sn (Rd = registr ARM procesoru)
22 Přesuny dat VMOV Sn, # 1 načtení konstanty Sd := #
23 Přesuny dat VMOV Dn, Rd 2 přesun double (jsou zapotřebí dva CPU registry)
24 Přesuny dat VMOV Rd, Dn 2 přesun double (jsou zapotřebí dva CPU registry)
25 Přesuny dat VMRS APSR_nzcv, FPSCR 1 APSR flags := FPSCR flags (přenos příznaků)  
26 Přesuny dat VSMR FPSCR, APSR_nzcv 1 opak předchozí instrukce  
27 Přesuny dat VLDR.32 2 načtení jednoho registru typu single  
28 Přesuny dat VLDR.64 3 načtení jednoho registru typu double  
29 Přesuny dat VLDM.32 1+N načtení jednoho až N registrů typu single  
30 Přesuny dat VLDM.64 1+2×N načtení jednoho až N registrů typu double  
31 Přesuny dat VSTR.32 2 uložení jednoho registru typu single  
32 Přesuny dat VSTR.64 3 uložení jednoho registru typu double  
33 Přesuny dat VSTM.32 1+N uložení jednoho až N registrů typu single  
34 Přesuny dat VSTM.64 1+2×N uložení jednoho až N registrů typu double  
35 Operace se zásobníkem VPUSH.32 1+N uložení N registrů na zásobník  
36 Operace se zásobníkem VPUSH.64 1+2×N uložení registrů na zásobník  
37 Operace se zásobníkem VPOP.32 1+N přečtení N registrů ze zásobníku  
38 Operace se zásobníkem VPOP.64 1+2×N přečtení N registrů ze zásobníku  

13. Operace ze standardu IEEE 754, které nejsou implementovány

Některé operace, které jsou (velmi přesně) definovány v normě IEEE 754 resp. v její novější úpravě IEEE 754–2008, ve skutečnosti nejsou na jádrech Cortex-M4F implementovány, což znamená, že pokud se dané operace objeví ve zdrojových kódech překládaných programů, musí překladač namísto vygenerování pouhých několika instrukcí koprocesoru volat knihovní funkce, což je samozřejmě pomalejší (a taktéž je nutné pro tyto funkce vyhradit dostatečnou kapacitu paměti ROM). Mezi nepodporované operace či instrukce patří především:

  • Výpočet zbytku po dělení.
  • Zaokrouhlení hodnoty s plovoucí řádovou čárkou na celočíselnou hodnotu uloženou zpět do registru koprocesoru.
  • Porovnání hodnoty typu single s hodnotou typu double a naopak.
  • Konverze mezi desítkovým a binárním formátem. Desítkový formát používá jako základ exponentu konstantu 10 a nikoli 2, norma IEEE 754 definuje tři takového formáty: decimal32, decimal64 a decimal128.
  • Zpětná konverze mezi binárním a desítkovým formátem.

14. Odkazy na Internetu

  1. A tour of the Cortex-M3 core:
    http://community.arm.com/grou­ps/processors/blog/2013/11/04/a-tour-of-the-cortex-m3-core
  2. Five things you may not know about ARM Cortex-M:
    http://community.arm.com/docs/DOC-6912
  3. Divide and Conquer:
    http://community.arm.com/docs/DOC-8059
  4. MCU market turns to 32-bits and ARM
    http://www.eetimes.com/do­cument.asp?doc_id=1280803
  5. Cortex-M0 Processor (ARM Holdings)
    http://www.arm.com/produc­ts/processors/cortex-m/cortex-m0.php
  6. Cortex-M0+ Processor (ARM Holdings)
    http://www.arm.com/produc­ts/processors/cortex-m/cortex-m0plus.php
  7. ARM Processors in a Mixed Signal World
    http://www.eeweb.com/blog/arm/arm-processors-in-a-mixed-signal-world
  8. ARM Architecture (Wikipedia)
    https://en.wikipedia.org/wi­ki/ARM_architecture
  9. Cortex-M0 (Wikipedia)
    https://en.wikipedia.org/wi­ki/ARM_Cortex-M0
  10. Cortex-M0+ (Wikipedia)
    https://en.wikipedia.org/wi­ki/ARM_Cortex-M#Cortex-M0.2B
  11. Improving ARM Code Density and Performance
    New Thumb Extensions to the ARM Architecture Richard Phelan
  12. The ARM Processor Architecture
    http://www.arm.com/produc­ts/processors/technologies/in­struction-set-architectures.php
  13. Thumb-2 instruction set
    http://infocenter.arm.com/hel­p/index.jsp?topic=/com.ar­m.doc.ddi0344c/Beiiegaf.html
  14. Introduction to ARM thumb
    http://www.eetimes.com/dis­cussion/other/4024632/Intro­duction-to-ARM-thumb
  15. ARM, Thumb, and ThumbEE instruction sets
    http://www.keil.com/suppor­t/man/docs/armasm/armasm_CEG­BEIJB.htm
  16. An Introduction to ARM Assembly Language
    http://dev.emcelettronica­.com/introduction-to-arm-assembly-language
  17. Processors – ARM
    http://www.arm.com/produc­ts/processors/index.php
  18. The ARM Instruction Set
    http://simplemachines.it/doc/ar­m_inst.pdf
  19. Instrukce typu SIMD na mikroprocesorech RISC
    http://www.root.cz/clanky/instrukce-typu-simd-na-mikroprocesorech-risc/
  20. Instrukce typu SIMD na mikroprocesorech RISC (2. část)
    http://www.root.cz/clanky/instrukce-typu-simd-na-mikroprocesorech-risc-2-cast/
  21. Instrukce typu SIMD na mikroprocesorech RISC (3.část – MIPS-3D a VIS)
    http://www.root.cz/clanky/instrukce-typu-simd-na-mikroprocesorech-risc-3-cast-mips-3d-a-vis/

Autor článku

Vystudoval VUT FIT a v současné době pracuje na projektech vytvářených v jazycích Python a Go.