RISC vs. CISC vs. GZIP

Nogle af os er gamle nok til at huske den religiøse RISC vs CISC krig der kørte i halvfemserne.

Idag er det ikke noget man tænker meget på, med mindre man faktisk sidder med næsen i noget maskinkode.

Jeg sidder og roder med at skrive en disassembler i Python til x86 arkitekturen (til mit lille PyRevEng) projekt og det giver stof til eftertanke i den retning.

Både IBM's mainframe instruktionssæt og Intels x86 familie, ser ud til at have fået hjulet i den samme fure: Hver gang man får en ny ide starter jagten på et hul i instruktionssættet hvor man kan klistre den ny feature på.

Resultatet er at en instruktion på x86 idag kan være op til 15 bytes lang:

Et antal "legacy prefix" (CS:, DS:, ES:, SS:, LOCK: REP: osv)
Et REX prefix, der i 64 bit mode giver dobbelt så mange registre.
En Instruktionskode på 1 eller 2 bytes
En byte der specificere address-mode
En byte der skruer løvefødder og gesvejsninger på address-mode
Et offset til address-mode (1, 2 eller 4 bytes)
Et konstant (1, 2 eller 4 bytes)

Hertil kommer så de fem forskellige interne modes CPUen kan befinde sig i, inklusve disses sub-modes: (Real, v86, protected(16|32), long compat(16|32) og "rigtig long" der er en 32 bit mode med 64bit tilvalg gennem prefix bytes. Hertil VM, SMM og andre obscure supervisor modes) og endelig diverse extensions med obskure navne som "3DNow!" og "Screaming Sindie" og den slags.

Vi er kommet langt fra den første RISC computer, der kun havde 18 instruktioner: JMP, JSR, ISZ, DSZ, LDA, STA, ADD, SUB, NEG, ADC, MOV, INC, COM, AND, DIx, DOx, NIO og SKP.

Men dengang var hardware dyr og derfor var det smart at bits i instruktionerne kunne hive direkte i hardware signaler uden for mange dikkedarer.

Når man bruger milliarder af transistorer på at bygge en CPU, er det sådan set lige meget og man bør ikke længere opfatte instruktionssættet som noget der har noget med hardware at gøre overhovedet, men derimod som en kommunikationsprotokol.

Den lunte fangede AMD med Athlon, som i virkeligheden består af en RISC-CPU med frontend-logik der oversætter X86 instruktioner til "rigtige" instruktioner.

ARM har også lavet et lidt tilsvarende trick med deres "thumb" instruktionssæt, der er en light-variant af de normale ARM instruktioner, smallere felter hist og her, som derfor fylder mindre plads.

I det lys giver et CISC instruktionssæt muligvis god mening, forudsat man designer det som en Huffman kode, så de mest brugte instruktioner er de korteste kodeord og sjældnt brugte eller meget langsomme instruktioner har lange kodeord.

Og når vi så har sagt det, er der jo nærliggende faktisk at gøre det til en Huffmankodning...

Al maskinkode, hvad enten man skriver det i hånden eller en kompiler spytter det ud, består af grupper af instruktioner adskilt af jumps, subroutinekald og andre afbrydelser.

Når den nu er igang med at tygge på mit program kunne en compiler ligeså godt komprimere disse "basic-blocks" med en huffman kode, eller for den sags skyld med gzip og CPU'en kunne så gunzip'e instruktionerne som en del af afkodningen.

Hvis komprimeringen ellers gør sit arbejde, sparer vi CPU-RAM båndbredde, hvilket stort set er den dyreste resource der findes i en computer idag.

Er der nogen der mangler en projektopgave ?

phk

Kommentarer (79)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
Svante Jørgensen

Spændende læsning!
Jeg er ikke den store hardware/assembler haj, men komprimeringen du forslår ville så være en helt ny måde at kommunikere mellem maskininstruktioner i RAM og eksekveringen i CPU'en?

Altså skal der bygges (endnu) en oversætter oven på CPU'en hvis den ikke er specialbygget til natively at forstå zip'ede instruktioner.

Desuden skulle der også et ekstra led på compileren der skulle zippe maskininstruktionerne.

Det sværeste bliver nok at overtale mainstream hardware producenter til at implementere denne nye oversætter i deres CPU'er. Men du har ret, som projektopgave er det en spændende ide.

PS. (Med risiko for at lyde dum) Tillader almindelige forbruger-OS'er som Linux og Windows at man sender de instruktioner til CPU'en som man har lyst til, uanset om de er "lovlige" eller ej?

  • 0
  • 0
Jon Bendtsen

Jeg synes din ide er en god projekt opgave og værd at undersøge, hvis det ikke allerede er undersøgt til bunds.

Jeg tror dog ikke der er så meget at hente ved at komprimere, for hvordan vil du komprimere registrene? givet der ikke så mange.

Hvad med stak CPU'er nu vi er i gang? Som kun kan lave instruktioner på de n=2? øverste registre på stakken? resten må man push, pop, osv. til. Du må da kunne køre med en helt utrolig frekvens.

  • 0
  • 0
Michael Jensen

Antallet af transistorer brugt på rent faktisk at decode/udføre en instruktion er meget lille i forhold til de milliarder af transistorer der findes i de store CPUer. Så lidt ekstra Huffmandekodning på instruktionsbasis vil ikke betyde noget. Hvilket er hvad der i princippet er udnyttet i ARMs Thumb og MIPS' MIPS16 (og det selv om ingen af deres processorer er i nærheden at milliarder af transistorer, tælles mere i få millioner).

Det bliver lidt mere problematisk hvis man begynder at Zippe større blokke. Man risikere hurtigt at overheaded bliver større end det du spare. Hver kode-blok (kode mellem jumps) er ca 6 instruktioner (hvad jeg har fået fortalt af en compiler ekspert). Så der skal ikke meget til før man har hentet instruktioner ind i CPUen, for at kunne dekode en større blok instruktioner, der aldrig blive udført. En cache linie (16-64 bytes) er nok den største blok man vil kunne zippe som en blok. Og så lille en blok er det nok begrænset hvad den kan komprimeres. Så vil et dedikeret instruktionssæt, som f.eks dem ovenfor nævnt, nok være meget mere velegnet.

Men et andet sted man kunne spare en masse båndbredde er hvis man zippede data. F.eks er det jo velkendt at det meste data jo består af nuller. Og de kan som bekendt pakkes ret grundigt. Så selv en enkelt cache linie kan ofte komprimeres rigtig meget.

  • 0
  • 0
Michael Jensen

"Jeg tror dog ikke der er så meget at hente ved at komprimere, for hvordan vil du komprimere registrene? givet der ikke så mange."

Ved ikke så meget om ARMs Thumb, men For MIPS16 har du (hvis jeg husker rigtigt) kun direkte adgang til de 8 af 32 i en 16 bit instruktion samt at du kun kan specificere 2 registre og ikke 3. Så f.eks du kun kan udføre RegA = RegA + RegB, og ikke RegA = RegB + RegC som i MIPS32/64. Dvs du bruger 6 bit af en 16 bit instruktion på at specificere registre, i stedet for 15 i en 32 bit instruktion. Hvis du vil tilgå de andre 24 registre, der ikke er direkte adgang til, kræver det brug af f.eks 32 bit instruktionerne i MIPS16.

  • 0
  • 0
Lasse Reinholt

En x64 kerne har typisk 32 KB L1 instruktionscache, og hastigheden fra denne til dekoderen er tilstrækkelig.

Hastigheden fra main memory og L2 til L1 er vigtigere, men hvis formålet er hurtigere kodeafvikling, så er latenstiden vigtigere end båndbredden fordi kodeeksekveringen efter et branch kan fortsætte så snart første instruktion er overført, mens resten af burst transaktionen fortsætter asynkront. Samme princip gælder jo for data, ikke kun kode.

Og et ekstra lag af kompression vil jo ikke mindske latenstiden.

I øvrigt komprimerer zlib maskinkode til ca. 50% af oprindelig størrelse, og det er med både LZ + huffman. Det er ikke specielt meget, og algoritmen er ret kompleks.

Se ftp://amd64gcc.dyndns.org/WORLDCOMP10/2010%20Papers/ESA5179.pdf

Fundet på 30 sekunder med Google

Den er ikke om det samme som PHK's ide, men derimod om at spare ROM. Ikke om at øge hastigheden af kodeeksekvering.

Hvis man skulle tilføje kompression, skulle man måske tilføje det isoleret til en BUS protokol og holde CPU'en udenfor. Sådan ville data også få gavn af kompressionen. Jeg kan bare ikke se, hvordan man skulle kunne gøre det uden at øge latency med nogle clocks.

  • 0
  • 0
Michael Jensen

Båndbredde er sjældent et problem internt på en chip. Om en bus er 32 eller 256 bit bred betyder ikke det store. Så det giver ikke meget mening at komprimere fra f.eks L1 cache til instruktions dekodning. Samtidig, som sagt, er latency er alt afgørende på det her niveau.

Det er kun data/instruktions overførelser fra extern hukommelse til intern cache det giver mening at diskutere båndbredde. Latency betyder også noget men om det tager 200 CPU clockcyckler eller 205 er lidt ligegyldigt. Specielt hvis man måske kan spare 20 clockcyckler på at overføre mindre data.

Så hvis man begynder at komprimere ting kunne man f.eks have tingene komprimeret i extern hukommelse og L2 cahce, mens det var blevet pakket ud i L1 cachen. Hvis jeg husker rigtigt så sker omkodningen af x86 til risk-instruktioner på et tidligt tidspunkt, så det der ligger i cachen nærmest instruktions dekodningen er risk-instruktioner og ikke x86.

  • 0
  • 0
Finn Christensen

@Jon

"Hvad med stak CPU'er nu vi er i gang? Som kun kan lave instruktioner på de n=2? øverste registre på stakken? resten må man push, pop, osv. til. Du må da kunne køre med en helt utrolig frekvens"

En variant af noget lignende eksister allerede.. FORTH eller GForth
http://en.wikipedia.org/wiki/Forth_%28programming_language%29

Prøvede FORTH i nogen tid langt tilbage i tiden, og ja den var meget hurtig, især med datidens langsomme CPU'er.

  • 0
  • 0
Jesper Louis Andersen

Du kan måske hurtigt dekode en masse instruktioner, men maskinen er nu engang begrænset af hvor bred dens initielle instruction issue buffer er. Moderne CPU'er æder typisk en 4-6 insns per klokcykel (trace cache og lign. ignoreret). Hvis du kan pakke dine instruktioner bedre, så kommer du bare til at vente på issue-bufferen i mange tilfælde fordi der ikke er plads.

Større instruktioner ville fylde mere i cache'en, men spørgsmålet er om det kan måles i praksis. Specielt set i forhold til en standard RISC-arkitekturs 4-byte opcodes. Det er klart at hvis I-cache på L1 er i problemer, så er det muligvis en sjov ting at lege med. Men er den ofte det?

Projektet er sådan set "ligetil". Instrumenter valgrinds "cachegrind" til at tage højde for komprimerede instruktioner og se hvor meget det eventuelt hjælper for programmer der må forventes at have "problemer" med dette. Specielt kan man også regne ud hvor meget det her egentlig er et problem i forhold til eksisterende programmer.

  • 0
  • 0
Jesper S. Møller

Er det ikke primært for en VLIW arkitektur, man kunne forestille sig at dette gav mening, én hvor man kan vha. conditional execution med fordel kan pipeline mere end én basic block ad gangen? Koden vil da være større, og netop instruktionscache og -fetch kan gå hen og blive

Og hvad med SSE, 3DNow, eller alle de andre freebies som Moore og co tilbyder når nu fysikerne ikke kan give os højere frekvens? De instruktioner passer jo slet ikke ind i en LWIV model, eller?

Men jeg kan slet ikke finde et egnet simulatorframework til at forsøge dette i?

  • 0
  • 0
Carsten Sonne

Set fra sidelinjen, har jeg altid undret mig over CISC arkitekturens succes - ikke for at genoplive halvfemsernes krig, men alligevel. Hardware, herunder CPU teknologi, er gået i retning mod større og større kompleksitet - selvfølgelige for at kunne leve op til morgendagens krav. Jeg er dog ikke så sikker det nødvendigs er en ”rigtige” filosofi blot at skalere op mod det uendelige.

Lige før transistoren udføre arbejdet ligger ALU komponenter. Det er de der udføre det faktiske arbejde. Resten er bare flytten rundt på bits og timing. ALU komponenterne styres med microcode. Over microcode ligger så CPU'ens API – instruktionssættet. Jeg kender ikke arkitekturen i AMDs Athlon processor, men det lyder til der ligger endnu et lag oven på instruktionssættet.

Spørgsmålet er hvor skal grænsen for næste abstraktionslag gå imellem hardware og software. Hvis ikke jeg tager fejl, er den egentlig sparsomme ressource regnekraft. Det næste spørgsmål er om regnekraften udnytte bedre ved at hardkode komplekst logik ind i hardwaren – selvfølgelig set i forhold til antallet af transistor og dermed groft sagt pris i kr/øre.

Uden at have det andet end maven, tror jeg faktisk bedre det kunne betale sig at fokusere på rå simple maskinkraft, ala RISC, og så lade specialiseringen foregå på software siden. Det må alt andet lige, være mere effektivt end hardkodning direkte i hardwaren – igen set ift. udnyttelse af regnekraft.

Mere grundlæggende er filosofien, at på tidspunk bliver ting så komplekse, at det værd at søge tilbage til rødderne. Det virker til CPU arkitektur er ved at nå dertil – specielt set i lyset af nye muligheder med flerkernet processorer. Eller måske er jeg bare naiv ?

  • 0
  • 0
Carsten Sonne

"Jeg tror du overser hvor stor en del af computers arebejde der i praksis kun er "at flytte rundt på bits"."

Ja, det er primært ift. I/O - og informationer ud og ind af systemet er vel trods alt en sekundær funktion. L1, L2 og L3 cache udgør jo netop kompensation for "flytten rund" under beregning.

  • 0
  • 0
Torben Mogensen Blogger

En stor del af grunden til, at CISC ikke tabte til RISC var, at antallet af transistorer, man kunne bruge i en CPU steg eksponentielt. Det betød, at det overhead, som CISC giver kunne skjules ved f.eks. at oversætte CISC til RISC-lignende mikroinstruktoner, som kan scheduleres bedre end større CISC-lignende instruktioner. Det koster i transistorer, men når man har rigeligt af dem, betyder det ikke så meget.

En anden måde man kan udnytte flere transistorer er ved at sætte flere CPU'er på en chip. Og her begynder det så at blive et problem med den ekstra kompleksitet, som CISC giver: Der er ikke plads til så mange CPU'er på chippen, hvis de er mere komplekse. Men da man i 90'erne ikke rigtig vidste, hvordan man skulle udnytte multikerne CPU'er i almindelige Windows PC'er, var det ikke den vej, man gik.

Men nu kan ethvert OS med respekt for sig selv udnytte flere kerner, og selv enkelt programmer bliver rutinemæssigt programmeret til dette. Samtidigt er man blevet mere opmærksom på strømforbrug, dels fordi den stationære PC er ved at uddø og dels fordi strøm og afkøling er blevet en væsentlig del af omkostningen ved serverparker. Så nu begynder den ekstra kompleksitet fra CISC at bide igen: Intel har tabt markedet for små bærbare enheder til ARM, og selv serverfabrikanter begynder at snakke om at bruge ARM.

  • 0
  • 0
Torben Mogensen Blogger

Jeg tror du overser hvor stor en del af computers arebejde der i praksis kun er "at flytte rundt på bits".

Det er ganske rigtigt ofte en væsentligere del af arbejdet end ALU-operationer, og det koster en del mere, specielt i multikerne CPU'er med delt lager, hvor lageret nemt bliver en flaskehals. Men det er ikke primært kodebits, der er problemet (kode fungerer typisk godt sammen med cache), det er data. Så man vil få en væsentligt større gevinst ved at komprimere data frem for at komprimere instruktioner.

  • 0
  • 0
Ole Wolf

På Aalborg Universitet undersøgte bl.a. Jack Andersen (der desværre døde af kræft for få år siden) muligheden for at fremstille en processor med et minimalt instruktionssæt med henblik på optimering af hukommelsesforbruget.

For det første var instruktionssættet og antallet af registre meget lille, hvorved instruktionsordbredden blev lille. Men så vidt jeg husker, så havde de endvidere i de forudgående analyser undersøgt hvilke former for operationer, der blev brugt oftest, og indrettet instruktionssættet og antallet af registre efter dette.

Min primære bekymring omkring et entropikodet instruktionssæt går mest på cache-linjer og den slags, men jeg må her indrømme, at jeg har fulgt meget lidt med på området de seneste årti.

  • 0
  • 0
Torben Mogensen Blogger

Ved variabel instruktionslængde kan man ganske rigtigt risikere, at en instruktion ligger henover to cache lines, hvilket er skidt. Man kan forhindre dette ved at indsætte no-operation instruktioner, men så mindskes fordelen i kodetæthed. Hvis cachelinjerne er meget længere end den længste instruktion, er det dog ikke så slemt. Hvis for eksempel instruktioner er 1-4 bytes lange og en cachelinje er 32 bytes lang, er det maksimale "tab" 3 bytes per cachelinje, altså under 10%. Ved omordning af instruktioner kan man reducere problemet, men det forsvinder ikke helt.

Selv om man kan mindske instruktionsstørrelsen ved at reducere antallet af synlige registre, så vil et lille antal registre øge antallet af lagerreferencer ([i]spills[/i]), hvilket gør programmerne både større og langsommere. Det optimale antal registre afhænger af programmerne, så der er ikke noget entydigt bedste valg. En bedre løsning er at have kompakte instruktioner, der kun kan bruge et lille antal registre, og større instruktioner, der kan bruge flere. Den ide bruges både i Thumb, Mips16 og x86-64. Transputeren havde en variant af samme ide: Instruktioner kunne bruge 8-bit indlejrede konstanter, men præfiksinstruktioner kunne specificere 8 ekstra bits ad gangen op til i alt 32. Transputeren brugte dog en fast 16-bit instruktionslængde, så præfiksinstruktionerne var ret dyre i plads.

Tilsvarende giver toadresseinstruktioner (hvor destinationsregistret er det samme som det ene argumentregister) typisk mere kompakt kode end treadresseinstruktioner, dog med den pris, at der af og til skal bruges extra MOVE instruktioner. En analyse, som ARM lavede før Thumb, viste dog, at det samlet set giver en pladsgevinst. En superskalar processor kan typisk schedulere MOVE instruktionerne samtidigt med andre instruktioner, så de ekstra instruktioner behøver ikke at koste noget i tid.

Hvis først man har et instruktionssæt i stil med Thumb2 (der modsat det originale Thumb instruktionssæt frit kan blande 16-bit og 32-bit instruktioner) tror jeg dog ikke, at man kan vinde meget ved kodekomprimering, med mindre man har en compiler, der laver aggressiv udrulning af løkker og inlining af funktionskald. Og her vil en mere naturlig komprimering så være at lade være med det.

Så er der (som tidligere nævnt) meget mere at hente ved at komprimere data. Der er f.eks. lavet algoritmer, der søger i komprimerede tekster i stedet for først at dekomprimere teksterne og derefter søge i de ukomprimerede tekster. Mere enkelt kan man ofte vinde en del ved at bruge 16- eller 8-bit heltal i tabeller, der ikke har brug for 32- eller 64-bit værdier.

  • 0
  • 0
Lasse Reinholt

ALU komponenterne styres med microcode. Over microcode ligger så CPU'ens API – instruktionssættet.

I øvrigt er x64 instruktionssættet jo netop en slags kompression af mikrokode - for at kommentere artiklen :)

Mere grundlæggende er filosofien, at på tidspunk bliver ting så komplekse, at det værd at søge tilbage til rødderne. Det virker til CPU arkitektur er ved at nå dertil – specielt set i lyset af nye muligheder med flerkernet processorer. Eller måske er jeg bare naiv ?

CISC's fordel er, at funktionalitet kan udføres med færre instruktioner. Lad os push'e 64-bit værdi'en 0x0123456789abcdef på stakken på RISC:

1) gem 0x01234567 i nedre 32 bits af $r1
2) gem 0x89abcdef i øvre 32 bits af $r1
3) subtraher 8 fra $sp
4) gem $r1 på adresse $sp

Jeg er pænt rusten i RISC assembler, så der er måske fejl. Men på x64 er det blot:

1) push 0x0123456789abcdef

Det er altså 4 instruktioner mod 1. Man kan også blot tælle linjer i disassembly fra diverse kode og sammenligne antallet.

Jeg har den opfattelse, at jo større helhedsbillede, man kan give CPU'en af, hvad du ønsker at gøre, jo bedre kan den optimere og lave genveje.

Jeg håber også, at vi en dag får native bounds checking og lign. sådan at managed kode kan eksekvere lige så hurtigt som native kode gør i dag.

  • 0
  • 0
Carsten Sonne

Selvfølgelig er der altid trade-offs. Modsætninger findes og man kan ikke få alt. For mig og se består valget mere i at finde nogle grundprincipper at arbejde ud fra - ikke at nogle sådan hermed er evigt statiske.

Jeg skal ikke gøre mig klog på caching og cacheliner heller - jeg kender ikke teknikken godt nok i detaljer. Jeg vil alligevel have en tilbøjelighed til at finde Jack Andersens tanker interessante.

Princippet om entropikodet instruktionssæt, må holde. På samme måde som nogle bogstaver (og ord) forekommer med en højere frekvens, og derfor bl.a. sidder mere centralt placeret på QWERTY tastaturet, så må præferencer til visse instruktioner giver mening.

"Hukommelse issues" på flerkerne processorer virker som en mere interessant udfordring.

  • 0
  • 0
Ole Wolf

RISC og CISC siger ikke nødvendigvis noget om størrelsen af et program. Det siger noget om, hvor komplicerede operationer, en enkelt instruktion udfører. Evnen til at komprimere programkoden handler om, hvorvidt man har et fixed-width instruktionssæt eller ej. Både RISC og CISC kan være fixed-width eller variable-width.

I praksis giver evnen til at løse komplicerede operationer i én instruktion, samt det forhold, at CISC-instruktionssæt traditionelt er variable-width, dog kortere kode.

Det er også værd at notere sig, at en ren load/store arkitektur, som oftest også kombineres med et RISC-instruktionssæt, er det nemmeste at forholde sig til for en out-of-order-processor. Da Intel introducerede Pentium Pro (eller var det II eller III?), splittede den flere af CISC-instruktionerne op i micro-ops, som var en slags RISC load/store-instruktioner.

  • 0
  • 0
Lasse Reinholt

Det var da et dårligt eksempel at sammenligne 32 bit RISC med 64 bit CISC.

Så vidt jeg husker, kan man med 32-bit RISC kun loade 16-bit immediates ad gangen (for at holde den samlede opkode+imm instruktionslængde på under 4 bytes?), så jeg antog at det samme gælder 64-bit RISC? Nå, kan være jeg tager fejl, men så er det stadig 3 instruktioner vs 1 :)

  • 0
  • 0
Lasse Reinholt

Princippet om entropikodet instruktionssæt, må holde. På samme måde som nogle bogstaver (og ord) forekommer med en højere frekvens, og derfor bl.a. sidder mere centralt placeret på QWERTY tastaturet, så må præferencer til visse instruktioner giver mening.

Pænt dumt princip, da du på den måde ikke kan lave hurtige lookups. Du kan hente "Volume 1A: Instruction Set Reference" fra http://www.intel.com/products/processor/manuals/ eller se på http://www.c-jump.com/CIS77/CPU/x86/lecture.html hvordan instruktioner encodes.

Fx betyder 000 registeret eax, 001 = ebx, 002 ecx, osv. Nu er det sådan, at eax registeret anvendes hyppigere end de øvrige (da enkelte operationer af historiske årsager er hurtigere via eax).

Hvis eax derfor skulle encodes som fx 1, og ebx = 001, ecx = 010, osv, så kan du ikke længere hente registres indhold eller lave andre opslag via en simpel hardware MUX. Desuden vil resten af bitfelterne forskyde sig og kræve bitshifts.

Der er af den årsag ingen arkitektur, som i dag entropiencoder instruktioner med fx Huffman. Hverken Alpha, MIPS, Cell, ARM, Itanium, x86, x64, SH5, og det er der en grund til. Det laver havoc i lookups. Alle bruger alignede fixed bitfelter for hver variant af en instruktion :)

  • 0
  • 0
Poul-Henning Kamp Blogger

RISC og CISC siger ikke nødvendigvis noget om størrelsen af et program. [...]

I virkeligheden siger det nok mere om firma-filosofien hos dem der styrer instruktionssættet.

Både x86 og s/360/370/390/zS er meget langtlevende og meget dominerende instruktionssæt og det ser ud til at tilskynde knopskydning der ville kunne gøre ethvert RISC sæt til CISC over 25 år.

Poul-Henning

  • 0
  • 0
Poul-Henning Kamp Blogger

Der er af den årsag ingen arkitektur, som i dag entropiencoder instruktioner med fx Huffman. Hverken Alpha, MIPS, Cell, ARM, Itanium, x86, x64, SH5, og det er der en grund til. Det laver havoc i lookups. Alle bruger alignede fixed bitfelter for hver variant af en instruktion :)

Du har ret i at de ikke gør det, men ikke hvorfor.

Efter dekomprimerning kunne dit instruktionssæt se ud præcis som du måtte ønske dig og hvilke registre en compiler foretrækker er heller ikke vigtigt, det kan man klare ved at lade compileren bygge det dictionary der bruges til dekomprimering.

Grunden til at man ikke gør det, er at man hænger fast i en 1960'er forestilling om hvad instruktioner er og ikke magter at forklare det nye koncept for dem der skriver compilere, markedsføringsfolk og brugere.

Se blot hvorledes Itanics instruktionssæt blev modtaget (ikke CPU'en som sådan, det er en anden historie), det er ret smart udtænkt: Folk med forstand roste det, folk der faktisk skulle bruge det brækkede sig...

Poul-Henning

  • 0
  • 0
Ole Wolf

I virkeligheden siger det nok mere om firma-filosofien hos dem der styrer instruktionssættet.

Ja, det er ret imponerende, hvad Intel har måttet gøre ved deres processorer gennem tiden for at sikre binær bagudkompatibilitet. Da jeg i sin tid gennemanalyserede deres første out-of-order processor, og siden SSE-tilføjelser, tog jeg virkelig hatten af for, hvor velovervejede og opfindsomme mange af deres arkitekturelle tradeoffs var.

  • 0
  • 0
Lasse Reinholt

Folk med forstand roste det, folk der faktisk skulle bruge det brækkede sig...

Problemet er jo, at Itanium er svær at optimere til. Lad os tage Cell, som jeg selv har udviklet til i praksis. Udover manglende værktøjer, er det ekstremt kompliceret at optimere til.

Ethvert program kan compileres til Cell med gcc og køre fint. Men, det udnytter kun hovedkernen og kører ved lav hastighed. Det er en meget naiv compilering og afvikling.

Hvis du skal udnytte alle de specialiserede kerner, bliver det meget, meget komplekst. Det er fint for projekter, hvor en lang dyr udviklingstid tjener sig ind, fx i forskning - proteinfoldning i biotek, hos CERN og whatnot. Altså alle dem, du kalder "folk, som har forstand".

Men for de fleste typer af øvrige "business apps" er udviklingstiden vigtig. Derfor døde Cell. Så vidt har Itanium samme problem.

Der er jo ikke noget galt med Itanium eller Cell, det passer bare ikke til den tænkte målgruppe.

Efter dekomprimerning kunne dit instruktionssæt se ud præcis som du måtte ønske dig og hvilke registre en compiler foretrækker er heller ikke vigtigt, det kan man klare ved at lade compileren bygge det dictionary der bruges til dekomprimering.

Så er vi tilabge til spørgsmålet, om

1) Kan det gøres uden at øge latenstiden?
2) Kan den eventuelt øgede latenstid opvejes af ca. 50% kompression?

  • 0
  • 0
Jesper Louis Andersen

Jeg er pænt rusten i RISC assembler, så der er måske fejl. Men på x64 er det blot:

1) push 0x0123456789abcdef

På en digital alpha vil du bare have 0x0123456789abcdef i hukommelsen og så køre:

1) ldq $gp, offset

hvor gp-registret er sat til at pege på den pågældende funktions offset-table.

Det koster ganske vist et memory-load, men typisk er de konstanter du loader meget mindre. Er konstanten lille nok, så virker et MIPS-style immediate add (ADDI) (eller en literal i Alpha ISA). Er konstanten lidt større, så har alpha lda og ldah. Og hvis konstanten er en multipel af 4 eller 8, så er der scaled adds.

  • 0
  • 0
Jesper Louis Andersen

@Lasse Reinholt:
Det var da et dårligt eksempel at sammenligne 32 bit RISC med 64 bit CISC.

Der er tale om en 64bit RISC maskine, men man har valgt at holde instruktionssættet nede på 4 byte opcodes i mange tilfælde alligevel. 8 byte instruktioner er lige i overkanten for det meste. Det er ikke ualmindeligt at man skal ud i flere instruktioner, hvis man vil populere et 64-bit register fuldt.

  • 0
  • 0
Lasse Reinholt

Der er ikke mange CPU'er i daglig drift der ikke står og triller tommelfingre mens de venter på memory access, der er ret meget at vinde.

Det er jo netop derfor jeg skrev latenstid, og ikke båndbredde. Når det krævede data er overført, overføres resten parallelt. Jeg har vist allerede nævnt det før, kan du ikke lige læse indlæggene? :)

  • 0
  • 0
Lasse Reinholt

På en digital alpha vil du bare have 0x0123456789abcdef i hukommelsen og så køre:

1) ldq $gp, offset

hvor gp-registret er sat til at pege på den pågældende funktions offset-table.

Det vil sige, at selv Alpha var begyndt at blive CISC-agtige? Rent faktisk, så kan ikke engang x64 det, som du beskriver (mem -> mem), så det må være noget ultra CISC :)

  • 0
  • 0
Jesper S. Møller

Det kan vel kort koges ned til at jo længere tid et instruktionssæt skal leve, desto mindre maskinnært og mere generelt er det nødt til at være.

Eksempelvis har SPARC et branch delay slot hvor pipelining gør at instruktionen efter et branch altid udføres. Det virkede smart i 1990, men når der er flere afviklingsenheder virker det arbitrært.

Zip-tanken falder nok derfor desværre i den maskinnære fælde, sammen med Cell, Itanium og Intel 860.

  • 0
  • 0
Jesper Frimann

Lasse Reinholt: Men for de fleste typer af øvrige "business apps" er udviklingstiden vigtig. Derfor døde Cell. Så vidt har Itanium samme problem.

Der er jo ikke noget galt med Itanium eller Cell, det passer bare ikke til den tænkte målgruppe.

Jeg vil sige at du tager fejl der, cell var/er ikke udviklet til 'business code'. Det er vist den lidt mere muskuløse fætter POWERX familien, der er udviklet til det.
Og både POWER og Itanium gør det faktisk ret godt i UNIX markedet.

Lasse Reinholt: Det vil sige, at selv Alpha var begyndt at blive CISC-agtige?

Ja bad boy'en i klassen er nok POWER, Performance Optimized With Enhanced Risc. Altså en RISC Processor på CICS epo :)

Og med hensyn til komprimering, så er komprimering af main memory på OS niveau altså noget som flere og flere overvejer, og bruger. I dag er der jo så meget processor punch i de maskiner man køber at den ressource, der begrænser maskinen er størrelsen af hukommelsen.
Og det er dumt at købe en maskine hvis den står og ikke laver noget 95% af tiden :)=

// jesper

  • 0
  • 0
Michael Jensen

I en parentes at bemærke :D :

"Princippet om entropikodet instruktionssæt, må holde. På samme måde som nogle bogstaver (og ord) forekommer med en højere frekvens, og derfor bl.a. sidder mere centralt placeret på QWERTY tastaturet, så må præferencer til visse instruktioner giver mening."

QWERTY tastaturet er et extremt dårligt eksempel, på det her, da det er designet til at sætte skrive hastigheden ned, så slå armene på de gamle maskiner kunne følge med.

  • 0
  • 0
Michael Jensen

"Der er tale om en 64bit RISC maskine, men man har valgt at holde instruktionssættet nede på 4 byte opcodes i mange tilfælde alligevel. 8 byte instruktioner er lige i overkanten for det meste. Det er ikke ualmindeligt at man skal ud i flere instruktioner, hvis man vil populere et 64-bit register fuldt."

Om RISC instruktionen er 4 eller 8 bytes er ligegyldigt i det her tilfælde. Da du kun vil få 2 eller 4 bytes Immediate værdi per instruktion. Det normale vil være at loade værdien fra Code Segmentet (f.eks liggende i toppen eller bunden af den stump kode som du er ved at eksekvere), hvorved den højst sandsynligvis allerede ligger i I-cache. Med mindre CPU architecture direkte forhindre dette.

Dertil, som sagt ovenover, er tilfælde hvor der skal loades en fuld 64 bit værdi sjældne. Det er typisk små offset til indekseringer der loades som er mindre end 16 bit.

  • 0
  • 0
Poul-Henning Kamp Blogger

Det vil sige, at selv Alpha var begyndt at blive CISC-agtige? Rent faktisk, så kan ikke engang x64 det, som du beskriver (mem -> mem), så det må være noget ultra CISC :)

Du har en underlig opfattelse af RISC hvis du tror det har noget med registrene og deres anvendelse at gøre.

Der er risc-designs der slet ikke har registre, alle operationer er mem-mem, eller endog mem-mem-mem.

Poul-Henning

  • 0
  • 0
Jesper Louis Andersen

Det vil sige, at selv Alpha var begyndt at blive CISC-agtige? Rent faktisk, så kan ikke engang x64 det, som du beskriver (mem -> mem), så det må være noget ultra CISC :)

Grrr, det er fordi jeg skriver noget vrøvl :)

Det skulle have været noget i retning af:

ldq $x, $gp, offset

så der er et target-register og operationen er R = *M[offset] i type (i.e., Mem -> Reg).

  • 0
  • 0
Jesper Louis Andersen

In princippet kunne man nok godt vælge flere bit end 16 til en immediate-value, men det er der nok få der gør for jeg tror ikke det bruges meget.

Dertil, som sagt ovenover, er tilfælde hvor der skal loades en fuld 64 bit værdi sjældne. Det er typisk små offset til indekseringer der loades som er mindre end 16 bit.

Ja. Alpha'ens literal-felt er 8bit, så de kaster sig over en ldq som du beskriver fra data-segmentet ret hurtigt ($gp peger ind i et segment kaldet .lita -- hvis min DEC Alpha-fu stadig er der, så mindes jeg det er der du gemmer konstanter over 31bit i størrelse). Men jeg tror ikke det er så ofte man har brug for det, så jeg er helt enig.

  • 0
  • 0
Torben Mogensen Blogger

I princippet kunne man nok godt vælge flere bit end 16 til en immediate-value, men det er der nok få der gør for jeg tror ikke det bruges meget.

Indeed. Der har været lavet undersøgelser om fordelingen af konstanter i programkode, og langt de fleste forekomster (mere end 90%) var 0, 1, -1 og 2. Dernæst kom andre encifrede værdier mens større værdier var under 5% tilsammen. Det kan altså (alt andet lige) betale sig at lave specialtilfælde for 0, 1, -1 og 2 (to bits) og lade større konstanter kræve flere eller større instruktioner. Ikke alle ALU instruktioner giver mening med 0 som argument, men sammenligninger er ofte med 0, så man kunne evt. lave forskellig indkodning af konstanter i aritmetik og sammenligning, så man i aritmetik f.eks. har -1, 1, 2 og 4 mens man i sammenligning har -1, 0, 1 og 2.

ARM har i øvrigt en meget interessant måde at indkode indlejrede konstanter: En konstant er 8 bits, som kan roteres med et lige antal bits til enhver lige position i maskinordet (så der bruges 5 bits til rotation). Enhver værdi af formen 2^n kan f.eks. indkodes som en enkelt konstant.

  • 0
  • 0
Ole Wolf

Det kan altså (alt andet lige) betale sig at lave specialtilfælde for 0, 1, -1 og 2 (to bits) og lade større konstanter kræve flere eller større instruktioner.

Way ahead of you: et betragteligt antal processorer har disse værdier "hard-coded" som "registre" internt i arkitekturen.

  • 0
  • 0
Torben Mogensen Blogger

Way ahead of you: et betragteligt antal processorer har disse værdier "hard-coded" som "registre" internt i arkitekturen.

Hvis du mener, at visse registre er

hard-coded

til at have disse værdier (ligesom register 0 på MIPS altid er 0), så er der ikke sparet ret meget i densitet: Du skal specificere 5 bits (på en 32-register maskine) for at få værdien, hvilket er mere end de to bits, der er nødvendigt. Jo, det er mere kompakt end f.eks. 16-bit konstanter, og har den fordel, at man kan bruge disse konstanter alle steder, hvor man kan specificere registre. Men det sidste viser også, at der er spild: Det er ikke alle steder, hvor man skal bruge et register, hvor det giver mening at have en lille konstant i stedet. F.eks. vil det sjældent give mening at bruge et af disse registre som destination for en operation.

  • 0
  • 0
Michael Jensen

F.eks. vil det sjældent give mening at bruge et af disse registre som destination for en operation.

MIPS' Reg0 bliver faktisk utrolig meget brugt både som source og som destinations register. Det forsimpler instruktionssættet en hel del. F.eks findes der faktisk ikke en decideret MOV instruktion. Men kan f.eks udføres som ADD Reg1=Reg2+Reg0. Dertil kommer instruktioner der i princippet findes i 2 versioner, selv om de gør det samme. F.eks de basale DI og EI instruktioner fås både med og uden destinations register (til at gemme den gamle værdi). Forskellen er den uden destinations register bare er specialtilfældet af den med, med destinations register specificeret til Reg0.

  • 0
  • 0
Jon Bendtsen

@Michael Jensen at 22. marts 2011 17:20

MIPS' Reg0 bliver faktisk utrolig meget brugt både som source og som destinations register. Det forsimpler instruktionssættet en hel del. F.eks findes der faktisk ikke en decideret MOV instruktion. Men kan f.eks udføres som ADD Reg1=Reg2+Reg0.

I disse dage hvor man skal spare strøm, er det så ikke lidt tåbeligt at lave en add bare for at flytte indholdet over til et andet register.

  • 0
  • 0
Poul-Henning Kamp Blogger

I disse dage hvor man skal spare strøm, er det så ikke lidt tåbeligt at lave en add bare for at flytte indholdet over til et andet register.

Nu begår du fejlen igen :-)

Hvorfor tror du at additionen bliver udført ?

ADD reg1=reg2+reg0

er bare vores måde at kommunikere vores intention.

CPU'en kan sagtens være bygget så den ikke spilder tid & energi på additionen når det er med register 0.

Poul-Henning

  • 0
  • 0
Michael Jensen

CPU'en kan sagtens være bygget så den ikke spilder tid & energi på additionen når det er med register 0.

Tror faktisk det er billigere energimæssigt at sende data gennem en eksisterende data path i ALU pipelinen, end at lave en ny. Og at lave en direkte MOVE funktion mellem registrene vil være en pestilens uden lige. Da der så skal læses data på et senere tidspunkt end når instruktionen har læserettigheder til registrene mens den bevæger ned gennem pipelinen.

  • 0
  • 0
Ole Wolf

CPU'en kan sagtens være bygget så den ikke spilder tid & energi på additionen når det er med register 0

Ja, hvis den kender indholdet af register 0. Men det gør den nok ikke. Det kunne lige så vel have været "add reg4 = reg31 + reg20", idet reg20 tilfældigvis er blevet sat reg20=0. Hvis den skulle spare tid og energi på additionen med 0, så skulle den først huske, at reg20 eller reg31 er 0.

Men så er der selvfølgelig det, at ALU'er kan være bygget på en måde, der shortcutter beregninger med simple værdier. Det skal jeg ikke kloge mig alt for meget på.

  • 0
  • 0
Jon Bendtsen

Hvorfor bruge en hel ALU med alle dens transistorer og dens bus, når det samme stykke arbejde kunne foretages af en langt simplere ekstra BUS? Nu er det i øvrigt sådan, at der findes skyggeregistre og whatnot, som fjerner de stalls, du nævnte.

Det her var præcis min tanke som lå bag mit spørgsmål.

  • 0
  • 0
Lasse Reinholt

Tror faktisk det er billigere energimæssigt at sende data gennem en eksisterende data path i ALU pipelinen, end at lave en ny. Og at lave en direkte MOVE funktion mellem registrene vil være en pestilens uden lige. Da der så skal læses data på et senere tidspunkt end når instruktionen har læserettigheder til registrene mens den bevæger ned gennem pipelinen

Hvorfor allokere en hel ALU med alle dens transistorer og dens bus, når det samme stykke arbejde kunne foretages af en langt simplere ekstra BUS? Så kan de 2-3 ALU'er lave mere nyttigt arbejde imens.

Nu er det i øvrigt sådan, at der findes skyggeregistre og whatnot, som fjerner de stalls, du nævnte.

Jeg tror ikke vi på version2 skal begynde at snakke den slags CPU design, det har ingen herinde vist ekspertise i. Det bliver ikke til andet end flyvske vendinger og holdninger uden hold i :)

  • 0
  • 0
Michael Jensen

Men så er der selvfølgelig det, at ALU'er kan være bygget på en måde, der shortcutter beregninger med simple værdier. Det skal jeg ikke kloge mig alt for meget på.

Tvivler jeg stærkt på nogen vil bruge tid på. For det første er ALU adderen (ja hele ALUen) kun en ud af et meget stort antal addere (beregningsfunktioner) i en CPU. Desuden er den mikroskopisk i forhold til alt det andet logik rundt om den. Selve ALUen fylder måske noget i stil med 0,1% af en CPU (før du begynder at putte cache ombord), alt efter hvad du medregner i ALUen. Hvad er et par tusind transistore for adderen ud af de milliarder f.eks Intel putter i deres.

Bare overheaded for at have sicilium/logik for 2 forskellige instruktion i stedet for 1 koster nok mere end at lave end ADD med 0.

  • 0
  • 0
Michael Jensen

Jeg tror ikke vi på version2 skal begynde at snakke den slags CPU design, det har ingen herinde vist ekspertise i.

Så må jeg vel hellere holde mig væk fra Version2, hvis der ikke må være folk med CPU design expertice herinde ;)

  • 0
  • 0
Michael Jensen

Hvorfor allokere en hel ALU med alle dens transistorer og dens bus, når det samme stykke arbejde kunne foretages af en langt simplere ekstra BUS? Så kan de 2-3 ALU'er lave mere nyttigt arbejde imens.

Ja i en Out-Of-Order CPU, men i en simpel in-order pipeline som de fleste processorer trods alt er, laver ALU ikke noget andet alligevel.

  • 0
  • 0
Jon Bendtsen

Det gør man også. De eksekveringsenheder, der i en given clockcykel ikke bliver brugt, bliver slukket i moderne processorer.

Ja, og ville det så ikke være smartere bare at slukke for ALUen og så lave register move på en eller anden anden måde?

  • 0
  • 0
Ole Wolf

Jeg husker ikke præcis, hvad der er motivationen for at undgå at trække tråde. Men jeg mener at huske, at det er fordi man er nødt til at trække reel kobber eller guld på die'en, hvilket både er en bøvlet produktionsproces og en fordyrende egenskab. Hæng mig ikke alt for meget op på det, men jeg har til dato kun set én chip (TMS320C4x-serien), der havde "for mange" busser i forhold til det strengt nødvendige.

  • 0
  • 0
Torben Mogensen Blogger

Tror faktisk det er billigere energimæssigt at sende data gennem en eksisterende data path i ALU pipelinen, end at lave en ny. Og at lave en direkte MOVE funktion mellem registrene vil være en pestilens uden lige.

I moderne CPU'er bliver en MOVE instruktion ofte implementeret med register renaming. Generelt vil en operation af formen Ri = Ri op Rj ikke overskrive det fysiske register, der indeholder den tidligere Ri, men bruge et nyt fysisk register og lade det gamle blive liggende indtil alle schedulerede instruktioner, der bruger den gamle værdi, er færdigafviklede. Denne registeromdøbning tillader mere [i]out-of-order[/i] eksekvering end hvis fysisk register == logisk register.

Det betyder, at Ri = Rj kan laves ved at omdøbe Ri til at bruge samme fysiske register som Rj. Opdateringer til Rj bruger nye registre, så det vil ikke overskrive Ri. Derfor behøver en MOVE instruktion slet ikke at flytte nogen værdi (udover at opdatere registeromdøbningstabellen).

Så i MIPS-tilfældet vil det klart være en fordel at genkende instruktioner, der reelt set implementerer en MOVE, dvs. Ri = R0+Rj, Ri = R0 OR Rj, Ri = Rj OR Rj, osv. og implementere dem ved registeromdøbning i stedet for at bruge ALU'en.

I MIPS bliver R0 ganske rigtigt brugt en del til f.eks. at implementere MOVE, men det er kun fordi der ikke findes en dedikeret MOVE instruktion. I det oprindelige MIPS design er alle instruktioner 32 bit, så der var ikke mulighed for at spare plads ved at lave en dedikeret MOVE instruktion, og i den oprindelige implementering skulle en værdi altid gennem ALU'en for at blive skrevet til et register, så en addition med 0 var ikke dyrere end end direkte flytning.

I MIPS16 er der dog indført en dedikeret MOVE instruktion, da 16-bit instruktioner har formen Ri = Ri op Rj, hvor man ikke kan lave en MOVE ved at lade det ene register være R0.

  • 0
  • 0
Jesper Louis Andersen

Ja i en Out-Of-Order CPU, men i en simpel in-order pipeline som de fleste processorer trods alt er, laver ALU ikke noget andet alligevel.

De fleste af os "stakler" der koder til x86/x86-64 og lignende antager uden problemer at CPU'en er OOO. En MOVE instruktion i sådan fætter er klaret af register renaming, så den er "gratis" i den forstand at den allerede er bagt ind i logikken omkring reservation stations.

I f.eks. Playstation 3, er CPU'en In-order. Men de nyere ARM'er kører dog OOO, så det lader til at du på higher-end hardware har en rimelig antagelse om at din hardware snart vil køre out-of-order.

Men elefanten er memorybussen til-fra CPU'en anyway. Det er den du vil have kontrol over hvis din kode skal performe godt. I dag betyder den nok mere end hvad du hælder i hovedet på CPU'en af instruktioner (indenfor en grænse, men jeg er som regel mere interesseret i optimere megareads/megawrites i stedet for insn count).

Linuxkernens perf-tool er pænt rart til at kigge på kørsler med.

  • 0
  • 0
Ole Wolf

I moderne CPU'er bliver en MOVE instruktion ofte implementeret med register renaming.

Ja, og det betyder i praksis, at man kan tillade sig at være så fræk at antage, at processoren har flere registre, end den egentlig har.

Register renaming giver (begribeligvis?) først problemer, når resultatet skal committes til brug. Dvs. primært i højoptimerede algoritmer, hvor resultatet FGM skal bruges indenfor få clockcykler, hvor man i praksis oplever, at register renaming kun giver en nogle få ekstra clockcykler at spille med. Men de er jo osse værd at tage med. :)

  • 0
  • 0
Poul-Henning Kamp Blogger

Ja, og det betyder i praksis, at man kan tillade sig at være så fræk at antage, at processoren har flere registre, end den egentlig har.

... Hvilket igen er med til at understrege at instruktionssættet er blevet en protokol der er afkoblet fra implementeringen af dens fortolkning.

Poul-Henning

  • 0
  • 0
Ole Wolf

instruktionssættet er blevet en protokol der er afkoblet fra implementeringen af dens fortolkning.

Ja og nej: Nej, fordi programmeringssprog jo altid er en variation af abstraktionsniveauer. På C niveau tænker man kun i behersket omfang på registre. På "almindeligt" assembler-niveau er de temmelig vigtige.

Ja, fordi hvis man virkelig skal optimere matematiske algoritmer med henblik på rå hastighed, så skal man også tænke på arkitekturen.

Det handler vel om, hvor man sætter sit abstraktionsniveau. På tilpas højt niveau kan man antage, at processor og operativsystem nok skal klare caches osv. På lavt niveau skal man stadig trille bits.

  • 0
  • 0
Jesper Frimann

Hvorfor? Hvad er det du mener virtuelle maskiner kan bringe til bordet?

Ikke for at være fræk, men der er jo også understøttelse for virtualizering i registre og instructions sættet på de fleste processorer i dag.

Så ja....

// jesper

  • 0
  • 0
Jon Bendtsen

@Jesper Frimann 25 marts 2011 13:46

Ikke for at være fræk, men der er jo også understøttelse for virtualizering i registre og instructions sættet på de fleste processorer i dag.

Ja, det ved jeg godt, jeg forstår bare ikke hvorfor Jimmy mente at virtualisering skulle bringes ind i denne diskussion om RISC vs. CISC vs. GZIP?

  • 0
  • 0
Jesper Frimann

Tja jo, måske som et eksempel på, at RISC i dag ikke er så 'reduceret', hvor

Stanford Universitets definition af en RISC processor er følgende: (det er den wikipedia henviser til):

RISC?
RISC, or Reduced Instruction Set Computer. is a type of microprocessor architecture that utilizes a small, highly-optimized set of instructions, rather than a more specialized set of instructions often found in other types of architectures.

som så også typisk var simplere processorer der kørte ved højere clock frekvenser.

Og hvis du ser på f.eks. et af de mest succesfulde RISC processor POWER så er det den jo langt fra den den simple processor uden 'special instruktioner', som RISC oprindelig var.
Du kan jo printe ISA'en ud og tygge dig igennem den:
http://www.power.org/resources/downloads/PowerISA_V2.06B_V2_PUBLIC.pdf

Der er både Vector instuktioner og og og ...

Så ja, jeg holder op med at trolde nu :)=

// Jesper god Weekend.

  • 0
  • 0
Log ind eller Opret konto for at kommentere