- PVSM.RU - https://www.pvsm.ru -
Изначально я написала этот документ несколько лет назад, будучи инженером по проверке ядра исполнения команд (execution core verification engineer) в ARM. Конечно, на моё мнение повлияла углублённая работа с исполнительными ядрами разных процессоров. Так что делайте на это скидку, пожалуйста: может, я слишком категорична.
Однако я по-прежнему считаю, что создатели RISC-V могли справиться гораздо лучше. С другой стороны, если бы я сегодня проектировала 32-или 64-разрядный процессор, то, вероятно, реализовала бы именно такую архитектуру, чтобы воспользоваться существующим инструментарием.
Статья изначально описывала набор команд RISC-V 2.0. Для версии 2.2 в ней сделаны некоторые обновления.
Набор команд RISC-V доведён до абсолютного минимума. Большое внимание уделяется минимизации числа инструкций, нормализации кодирования и т. д. Это стремление к минимализму привело к ложным ортогональностям (таким как повторное использование одной и той же инструкции для переходов, вызовов и возвратов) и обязательной многословности, что раздувает и размер, и количество инструкций.
Например, вот код C:
int readidx(int *p, size_t idx)
{ return p[idx]; }
Это простой случай индексирования массива, очень распространённая операция. Так выглядит компиляция для x86_64:
mov eax, [rdi+rsi*4]
ret
или ARM:
ldr r0, [r0, r1, lsl #2]
bx lr // return
Однако для RISC-V необходим такой код:
slli a1, a1, 2
add a0, a1, a1
lw a0, a0, 0
jalr r0, r1, 0 // return
Симплификация RISC-V упрощает декодер (т. е. фронтенд CPU) за счёт выполнения большего количества инструкций. Но масштабирование ширины конвейера — сложная проблема, в то время как декодирование слегка (или сильно) нерегулярных инструкций хорошо реализуется (основная трудность возникает, когда трудно определить длину инструкции: это особенно проявляется в наборе команд x86 с многочисленными префиксами).
Упрощение набора инструкций не следует доводить до предела. Регистр со сдвигом регистровой памяти — несложная и очень распространённая инструкция в программах, а процессору очень легко её эффективно реализовать. Если процессор не способен реализовать инструкцию напрямую, то может относительно легко разбить её на составляющие; это гораздо более простая проблема, чем слияние последовательностей простых операций.
Мы должны отличать «сложные» специфические инструкции CISC-процессоров — усложнённые, редко используемые и малооэффективные инструкции — от «функциональных» инструкций, общих для процессоров CISC и RISC, которые объединяют небольшую последовательность операций. Последние используются часто и с высокой производительностью.
JALR) используется и для вызовов, и для возвратов и для косвенно-регистровых переходов (register-indirect branches), где требуется дополнительное декодирование для предсказания ветвей
Rd = R1
Rd = R0, Rs = R1
Rd = R0, Rs ≠ R1
Rd ≠ R0, Rd ≠ R1)LR/SC строгое требование к поступательному продвижению для ограниченного подмножества применений. Хотя это ограничение довольно жёсткое, оно потенциально создаёт некоторые проблемы для небольших реализаций (особенно без кэша)
FP кодируются для 32, 64 и 128-битной точности, но не 16-битной (что значительно чаще встречается в аппаратном обеспечении, чем 128 бит)
2'b10 бесплатно
LR/SC находятся в том же расширении, что и более сложные атомарные инструкции, что ограничивает гибкость для небольших реализаций
LR/SC) не включают примитив CAS
Addr, CmpHi:CmpLo, SwapHi:SwapLo), но это, вероятно, наложит меньше накладных расходов на реализацию, чем гарантированное продвижение вперёд LR/SC, которое предоставляется в качестве заменыADD в RV32I и 64-битной ADD в RVI64 одинаковые кодировки, а в RVI64 добавляется ещё и другая кодировка ADD.W. Это ненужное усложнение для процессора, который реализует обе инструкции — было бы предпочтительнее вместо этого добавить новую 64-битную кодировку.
MOV. Алиас MV реализуется как MV rD, rS->ADDI rD, rS, 0. Оптимизацию MOV обычно выполняют высокопроизводительные процессоры (особенно нестандартные). Распознавание канонической MV в RISC-V требует немедленного осуществления операции OR в 12 бит
MOV инструкция MOV rD, rS, r0 фактически становится предпочтительнее канонической MOV, поскольку её легче декодировать, а в CPU обычно есть специальная логика для распознавания нулевого регистраJAL тратит 5 бит на кодирование регистра связи, который всегда равен R1 (или R0 для переходов)
Rbase+Roffset) или индексов (Rbase+Rindex << Scale).
FENCE.I подразумевает полную синхронизацию кэша инструкций со всеми предыдущими хранилищами, с ограждением (fenced) или без него. Реализациям нужно или очищать весь I$ на ограждении, или выискивать D$ и накопительный буфер (store buffer)
NOP на текущих процессорах, но имеет некоторое поведение на самых современных CPU
Автор: m1rko
Источник [1]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/assembler/325436
Ссылки в тексте:
[1] Источник: https://habr.com/ru/post/461785/?utm_campaign=461785&utm_source=habrahabr&utm_medium=rss
Нажмите здесь для печати.