ISA ошибок не прощает
–X86 – это исторически сложившееся недоразумение,– мэтр и в 80 не утратил полемического задора.
– Вообще-то ей принадлежит 95% серверного рынка, – вяло откликнулся я. Мне не хотелось вступать в спор на сто раз заезженную тему
– А я уже запутался в этих префиксах, — не унимался академик. – 15 байт на инструкцию, это немыслимо!
– Ну, не ice, конечно. Но у кого лучше-то?
– Да у кого угодно, хотя бы у ARM-a.
– Я все же не понимаю. Cложения с умножениями должны быть?
– Должны.
– И сдвиги c логическими операциями?
– Да.
– И загрузки с сохранениями тоже. Какая разница как они называются и кодируются?
Как обычно, правоту учителя я осознал много позже. Когда тоскливым зимним вечером сел писать декодер команд, чтобы как то себя развлечь. Простенький декодер для ARM мне удалось изобразить на VHDL (а знаю я его так себе) за пару дней. Правда, каюсь, у меня была шпаргалка. :)
Для X86 не удалось ни за неделю, ни за две, ни за месяц… Даже для базового набора.
Разница здесь даже не только в RISC (Reduced Instruction Set Computing) для ARM и CISC (Complex Instruction Set) для X86. Разница скорее в пути исторического развития. Больше 40 лет назад, а началось все в 1978 году, X86 ISA (Instruction Set Architecture) была вполне себе компактным набором команд со своей внутренней логикой. Но время шло, росла разрядность шин, расширялись регистры (включая SIMD), перманентно возрастало число команд. Тут один паренёк сделал интересную попытку просто посчитать число инструкций в Х86. То ли ему лень было открывать мануал и считать их, то ли он знал о существовании “безымянных” опкодов (команд, у которых даже названия нет), то ли верил во всемогущество логики. Как легко понять, логика оказалась бессильна. :) Кстати, я пытался найти график роста числа X86 инструкций по годам (или по поколениям). Пока не смог (может, есть у кого?). Зато нашел вот такую картинку.
Если честно, я не знаю, сколько сейчас в X86 ISA инструкций. Но хорошо помню все те, в разработку которых сам вкладывался, при этом не отдавая себе отчета в том, что каждый новый бит в ISA снабжается ярлыком “хранить вечно”. А «творцов» вроде меня в Intel было несколько тысяч. И битов для того, чтобы закодировать все их фантазии постоянно не хватало. :) К существующему набору команд добавлялись все новые префиксы: REX, VEX… Последнее четырехбайтовое (EVEX) расширение было введено для AVX-512. К слову, весь набор команд АRM (даже с учетом SVE) убирается в эти самые 4 байта. ARM изначально пошел другим путем, строя свою систему команд на базовых принципах простоты, компактности и расширяемости.
Разницу можно понять, если перейти с точки зрения программиста на точку зрения circuit designer. А она как известно состоит в том, что транзистор – отличная вещь, но переключается медленно, а энергию рассеивает безбожно. И при прочих равных, лучше бы их было поменьше. А теперь взгляните на алгоритм декодирования x86 инструкций(та задача, которую я пытался решить).
И, как говорится, почувствуйте разницу во входных трактах (front end) для ARM и X86. Тут можно возразить, что front end – это совсем небольшая часть ядра, всего около 10%. Да, но не надо забывать, что вся эта логика умножается ещё на количество ядер на чипе. А это уже серьезно. Eщё одно соображение, что front end – как раз та часть, которая ответственна за backward compatibility. Вы можете смело перелопатить или даже выкинуть back end. Intel, кстати, воспользовался этим в начале 2000-х, заменив архитектуру NetBurst (P4) на Core-M (P3). А вот front end сильно сократить не удастся. Хотя иногда очень хочется, потому что из существующей X86 ISA сейчас используется около 20%. Остальное – пережитки прошлого.
Другой недостаток огромной длины инструкций – относительно частые промахи в instruction cache. Грубо говоря, при равном размере кэшей, количество промахов будет тем больше, чем больше длина инструкции. Конечно, размер кэшей можно увеличивать. Но опять же, это транзисторы, которых могло бы не быть, будь инструкции покороче. По этой же причне я очень настороженно отношусь к разного рода VLIW (Very Long Instruction World) архитектурам. Впрочем, они обладают еще и тем недостатком, что для них очень сложно разрабатывать компиляторы. Тему компиляторов я до сего момента сознательно избегал, поскольку сам никогда их не разрабатывал. Хотелось бы послушать, что скажут знающие люди о прелестях разработки компиляторов для RISC, CISC и VLIW.
И все же, несмотря на огромный накопленный груз legacy, а может быть и благодаря ему, разработчики X86 оказались правы в главном. Принцип backward compatibility свято соблюдается в архитектуре с самого начала. Весь существующий софт работает на новом железе «из коробки». Именно это позволило построить столь глубокую и развитую экосистему вокруг архитектуры. И остается только снять шапку перед инженерами Intel и AMD, которые вопреки отнюдь не идеальному дизайну ISA, на протяжении многих лет сохраняют лидерство в серверном сегменте. Однако, груз legacy становится все тяжелее.