On 10/10/2013 10:33 AM, Pontus Pihlgren wrote:
Hej
Den här länkades till på ElektronikForum för ett tag sedan:
http://www.cs.colby.edu/djskrien/CPUSim/
Jag har inte testat själv, men det kanske kan vara något att labba med för er som vill göra en egen arkitektur.
Ooh, ser intressant ut! Själv sitter jag och plöjer igenom alla forskningsrapporter jag kan hitta om koddensitet. Jag kommer att ha väldigt ont om minne, så jag vill veta hur man designar en maximalt kompakt instruktionsuppsättning. De flesta rapporterna handlar dock om kodkomprimering, dvs antingen genom att man bara skriver ett jättetråkigt program som packar upp koden lite i taget när den ska köras, eller genom att man sätter en liten låda på minnesbussen eller mellan I-cachen och kärnan som dekomprimerar instruktionsströmmen on-the-fly. Störtlöjligt. De mer relevanta punkterna när det gäller designandet av en instruktionsuppsättning är dessa: * Variabel instruktionslängd, med vanliga instruktioner kodade med färre bittar * Instruktionsformat med korta immediates; de flesta konstanter är bara några bittar långa * De allra vanligaste konstanterna är 0 och 1; det är värt att ha specialinstruktioner för t.ex. ladda 0 och addera 1 * Allmänt en bra ide med specialinstruktioner för vanliga kombinationer, t.ex. push/pop, subrutinanrop, dekrementera-testa-hoppa * Relativ adressering; konditionella hopp t.ex. hoppar oftast bara några instruktioner bort. Små offsets är bra. * Flera adresseringssätt. [Register + offset] är jättevanligt, [register + register] inte. Indirekt adressering är i princip värdelöst. Immediates är jättevanligt. Autoinkrementerande adresseringssätt gör koden märkbart mer kompakt. * Instruktioner ska sätta flaggor så man slipper testinstruktioner * Divisionsinstruktioner hjälper, särskilt i program som skriver ut nummer, eftersom det blir en massa delande med 10 då. Ganska mycket av det här är väl rätt intuitivt, men det har även i de fallen varit rätt trevligt att få se siffror på hur det ser ut på riktiga arkitekturer och med riktig kod. På 8086 är t.ex. i en rapport 28,4% av alla operander minnesoperander, men bara 0,4% använder [reg + reg] för adresseringen. I koden för RSX på PDP-11 är [reg + offset] 17,3% av alla operander, 14,9% är immediate, och 15,2% är olika autoinkrementerande adresseringssätt, men en stor del av de senare är instruktioner som bara använts för att inkrementera ett register med 2, som alltså är ett fall som kanske skulle optimeras. Indirekt adressering är 1%. PDP-11 uppnår för övrigt väldigt hög koddensitet; i en jämförelse av koddensiteten hos handoptimerad assemblerkod på 21 olika arkitekturer vinner PDP-11, följd av CRISv32 (som jag aldrig har hört talas om), AVR och Z80. Alpha är riktigt dålig och Itanium är ett roligt skämt ha ha. På 8080 är 80% av alla hopp inom 127 bytes från hoppinstruktionen, på IBM System/370 är det 50-60%. På System/370 tillåts adressering med [reg + reg + offset], men så mycket som 95% av instruktionerna använder bara ett register. Undantaget är program som gör väldigt mycket arrayvandrande; där sjunker andelen minnesreferenser som bara använder ett register till omkring 80% i de exempel som undersökts av rapporten i fråga. Det är hur som helst värt att spara in bittarna som går till specifierandet av det andra registret och göra offsettet större, för offset av alla storlekar förekommer. Minnesadressering på System/370 är förresten totalt CP, läs om det om ni vill få er ett ta-sig-för-pannan-ögonblick. Hm oj, nu skrev jag mycket mer om det här än jag hade tänkt, och det mesta av det var kanske inte så intressant! :D Jag har snöat in ordentligt och har jättekul. Jag ska designa en skitbra arkitektur! Bjarni