RISC-V со временем займёт нишу дешёвых микроконтроллеров, но вопреки дизайну ISA, а не благодаря ему. Утверждение, что одна архитектура будет одинаково хороша и для суперкомпьютеров, и для крошечных микроконтроллеров, — иллюзия: этим задачам нужны противоположные свойства. Для простых устройств критичны задержка прерываний и плотность кода, а здесь RISC-V заметно хуже конкурента. На вход в прерывание и вызов C-обработчика уходит минимум 44 цикла, у Cortex-M0 — 27. Даже RV32E сокращает это до 38 циклов. Базовый набор не требует Zicsr, без него некуда сохранить регистры, аппаратного сохранения регистров нет. Вендорам приходится изобретать свои расширения вроде CLIC, чтобы догнать десятилетний Cortex-M0.
Сжатые инструкции тоже разочаровывают. В 16-битных инструкциях для store byte доступны смещения 0–3, для halfword — 0 или 2, тогда как Cortex-M0 позволяет 0–31 и 0–62. И эти store byte/halfword вообще не входят в расширение C, а вынесены в отдельное Zcb. Для высокопроизводительных ядер лучше всего подошли бы фиксированные 4-байтные инструкции, как в aarch64, но сжатый набор лишь мешает параллельному декодированию.
Ещё одна беда — адресация массивов. В базовой ISA нет режима «регистр + сдвинутый регистр», приходится делать shift, add и только потом load. Расширение Zba с SHxADD приняли лишь в 2021-м, через два года после базового спека, и всё равно на доступ к массиву уходит 6–8 байт кода против 4 у ARM. Qualcomm предлагал переработать кодировку, но инициатива никуда не пошла.
Хуже всего опциональность. Всё, что можно, объявлено необязательным: умножение, деление, user mode, supervisor mode, CSR, сжатые инструкции. Это роднит RISC-V с USB-C и RCS: формально стандарт, по факту ничего. Даже способ определить возможности CPU — CSR misa — сам опционален, может читаться как нули и недоступен из пользовательского режима. Системный таймер memory-mapped, но адрес implementation defined. И direct, и vectored mode в mtvec/stvec опциональны, ядро не знает, чего ждать. Оправдания виртуализацией и Popek & Goldberg не работают: x86 и ARM справляются, не пряча CPUID и CurrentEL.
Наконец, в RISC-V не хватает очевидной инструкции «проверить бит и перейти». В случайном aarch64-бинарнике нашлось 35 393 TBZ/TBNZ против 70 109 RET — то есть в среднем каждой второй функции такая инструкция нужна.