RISC-V 手册

我喜欢 RISC-V 和这本书,因为它们优雅——简洁、扼要且完整。书中的评论无偿提供了一些历史,设计的动机,以及一些对于各种架构的批评。
——C. Gordan Bell,微软公司成员,Digital PDP-11 和VAX-11 指令集架构的设计者

本书讲述了 RISC-V 可以做到什么,以及为什么它的设计师选择赋予它这些能力。更有趣的是,作者说出了为什么 RISC-V 省略了早期计算机中存在的一些东西。这些原因至少和 RISC-V 本身能做到什么与忽略了什么一样有意思。
——Ivan Sutherland,图灵奖获得者,被称作计算机图形学之父

RISC-V 会改变世界,这本书会助你成为改变的一部分。
——Michael B. Taylor,华盛顿大学教授

RISC-V 是学生学习指令集架构和汇编级编程的理想选择,而它们是以后用高级语言工作的基础。这本写得很清楚的书提供了对 RISC-V 的很好的介绍,再加上一些对其演化历史的深刻见解及与其它常见架构的比较。以过去的指令集架构为鉴,RISC-V 的设计者能够避免一些不必要的、不合理的特征,这让教学过程变得容易。即使它很简洁,它也足够强大,能在实际应用中广泛使用。很久以前我教过汇编编程的入门课,如果我现在去教这门课的话,我会很乐意用这本书作为教材。
——John Mashey,MIPS 指令集架构的设计者之一

这本书对于任何使用 RISC-V ISA 的人来说都是十分宝贵的参考。为了便于快速查阅,操作码按几种有用的格式呈现,这让编写和解释汇编代码变得简单。此外,对于如何使用这个 ISA 的解释和示例也让程序员的工作更容易。和其他 ISA 比较的部分很有意思,它们解释了 RISC-V 设计者们做出他们的设计决策的原因。
——Megan Wachs,博士,SiFive 工程师

展开查看详情

1. 1 2018 RISC-V 手册 一本开源指令集的指南 DAVID PATTERSON, ANDREW WATERMAN 翻译:勾凌睿、黄成、刘志刚 校阅:包云岗

2.

3. 1 参考卡

4.2

5. 3 目录 参考卡 ..................................................................................................................................................... 1 致谢 ......................................................................................................................................................... 7 关于作者 ................................................................................................................................................. 9 前言 .......................................................................................................................................................10 译者序 ...................................................................................................................................................12 翻译团队 ................................................................................................................................................ 12 第一章 为什么要有 RISC-V?..........................................................................................................13 1.1 导言 ................................................................................................................................................. 13 1.2 模块化与增量型 ISA ................................................................................................................... 14 1.3 ISA 设计 101 ................................................................................................................................. 15 1.4 全书的总览.................................................................................................................................... 19 1.5 结束语 ............................................................................................................................................. 20 1.6 扩展阅读 ........................................................................................................................................ 21 第二章 RV32I:RISC-V 基础整数指令集 ......................................................................................23 2.1 导言 ................................................................................................................................................. 23 2.2 RV32I 指令格式 ............................................................................................................................. 23 2.3 RV32I 寄存器 ................................................................................................................................. 26 2.4 RV32I 整数计算 ............................................................................................................................. 27 2.5 RV32I 的 Load 和 Store .............................................................................................................. 29 2.6 RV32I 条件分支 ............................................................................................................................. 30 2.7 RV32I 无条件跳转 ........................................................................................................................ 31 2.8 RV32I 杂项 ...................................................................................................................................... 31 2.9 使用插入排序比较 RV32I,ARM-32,MIPS-32 和 x86-32 指令集........................... 32 2.10 结束语 .......................................................................................................................................... 32 2.11 扩展阅读 ...................................................................................................................................... 33 第三章 RISC-V 汇编语言 ..................................................................................................................41 3.1 导言 ................................................................................................................................................. 41 3.2 函数调用规范(Calling convention) ................................................................................. 41 3.3 汇编器 ............................................................................................................................................. 43 3.4 链接器 ............................................................................................................................................. 46 3.5 静态链接和动态链接 ................................................................................................................. 49 3.6 加载器 ............................................................................................................................................. 49 3.7 结束语 ............................................................................................................................................. 49

6.4 3.8 扩展阅读 ........................................................................................................................................ 50 第四章 乘法和除法指令 ................................................................................................................... 51 4.1 导言 ................................................................................................................................................. 51 4.2 结束语 ............................................................................................................................................ 53 4.3 扩展阅读 ........................................................................................................................................ 53 第五章 RV32F 和 RV32D:单精度和双精度浮点数.................................................................... 55 5.1 导言 ................................................................................................................................................. 55 5.2 浮点寄存器 .................................................................................................................................... 55 5.3 浮点加载,存储和算术指令 .................................................................................................... 56 5.4 浮点转换和搬运 ........................................................................................................................... 60 5.5 其他浮点指令 ................................................................................................................................ 60 5.6 使用 DAXPY 程序比较 RV32FD,ARM-32,MIPS-32 和 x86-32 ............................... 62 5.7 结束语.............................................................................................................................................. 62 5.8 扩展阅读 ........................................................................................................................................ 62 第六章 原子指令 ................................................................................................................................ 65 6.1 导言 ................................................................................................................................................. 65 6.2 结束语 ............................................................................................................................................ 67 6.3 扩展阅读 ........................................................................................................................................ 67 第七章 压缩指令 ................................................................................................................................ 69 7.1 导言 ................................................................................................................................................. 69 7.2 RV32GC,Thumb-2,microMIPS 和 x86-32 的比较 ...................................................... 71 7.3 结束语 ............................................................................................................................................ 71 7.4 扩展阅读 ........................................................................................................................................ 71 第八章 向量 ........................................................................................................................................ 75 8.1 导言 ................................................................................................................................................. 75 8.2 向量计算指令............................................................................................................................... 76 8.3 向量寄存器和动态类型 ............................................................................................................ 76 8.4 向量的 Load 和 Store 操作 ...................................................................................................... 78 8.5 向量操作期间的并行性 ............................................................................................................ 78 8.6 向量运算的条件执行 ................................................................................................................. 79 8.7 其他向量指令............................................................................................................................... 79 8.8 例子:用 RV32V 写成的 DAXPY 程序 ................................................................................. 80 8.9 RV32V,MIPS-32 MSA SIMD 和 x86-32 AVX SIMD 的比较 ......................................... 81

7. 5 8.10 结束语 .......................................................................................................................................... 83 8.11 扩展阅读 ...................................................................................................................................... 84 第九章 RV64:64 位地址指令 ........................................................................................................87 9.1 导言 ................................................................................................................................................. 87 9.2 使用插入排序来比较 RV64 与其他 64 位 ISA ..................................................................... 91 9.3 程序大小 ......................................................................................................................................... 93 9.4 结束语 .............................................................................................................................................. 93 9.5 了解更多 ......................................................................................................................................... 94 第十章 RV32/64 特权架构 ...............................................................................................................99 10.1 导言 ............................................................................................................................................... 99 10.2 简单嵌入式系统的机器模式 .............................................................................................. 100 10.3 机器模式下的异常处理 ....................................................................................................... 101 10.4 嵌入式系统中的用户模式和进程隔离 ............................................................................ 104 10.5 现代操作系统的监管者模式 .............................................................................................. 105 10.6 基于页面的虚拟内存 ............................................................................................................ 106 10.7 结束语 ....................................................................................................................................... 110 10.8 扩展阅读 ................................................................................................................................... 111 第十一章 RISC-V 未来的可选扩展 .............................................................................................. 113 11.1 “B”标准扩展:位操作 ............................................................................................................ 113 11.2 “E”标准扩展:嵌入式 ............................................................................................................ 113 11.3 “H”特权态架构扩展:支持管理程序(Hypervisor) ................................................. 113 11.4 “J”标准扩展:动态翻译语言 ............................................................................................... 113 11.5 “L”标准扩展:十进制浮点 ................................................................................................... 113 11.6 “N”标准扩展:用户态中断 .................................................................................................. 113 11.7 “P”标准扩展:封装的单指令多数据(Packed-SIMD)指令 ................................... 114 11.8 “Q”标准扩展:四精度浮点.................................................................................................. 114 11.9 结束语 ....................................................................................................................................... 114 附录 A RISC-V 指令列表 ............................................................................................................. 115

8.6 对这本 RISC-V 手册的称赞 我喜欢 RISC-V 和这本书,因为它们优雅——简洁、扼要且完整。书中的评论无偿提供 了一些历史,设计的动机,以及一些对于各种架构的批评。 ——C. Gordan Bell,微软公司成员,Digital PDP-11 和 VAX-11 指令集架构的设计者 本书讲述了 RISC-V 可以做到什么,以及为什么它的设计师选择赋予它这些能力。更有 趣的是,作者说出了为什么 RISC-V 省略了早期计算机中存在的一些东西。这些原因至 少和 RISC-V 本身能做到什么与忽略了什么一样有意思。 ——Ivan Sutherland,图灵奖获得者,被称作计算机图形学之父 RISC-V 会改变世界,这本书会助你成为改变的一部分。 ——Michael B. Taylor,华盛顿大学教授 RISC-V 是学生学习指令集架构和汇编级编程的理想选择,而它们是以后用高级语言工 作的基础。这本写得很清楚的书提供了对 RISC-V 的很好的介绍,再加上一些对其演化 历史的深刻见解及与其它常见架构的比较。以过去的指令集架构为鉴,RISC-V 的设计 者能够避免一些不必要的、不合理的特征,这让教学过程变得容易。即使它很简洁,它 也足够强大,能在实际应用中广泛使用。很久以前我教过汇编编程的入门课,如果我现 在去教这门课的话,我会很乐意用这本书作为教材。 ——John Mashey,MIPS 指令集架构的设计者之一 这本书对于任何使用 RISC-V ISA 的人来说都是十分宝贵的参考。为了便于快速查阅, 操作码按几种有用的格式呈现,这让编写和解释汇编代码变得简单。此外,对于如何使 用这个 ISA 的解释和示例也让程序员的工作更容易。 和其他 ISA 比较的部分很有意思, 它们解释了 RISC-V 设计者们做出他们的设计决策的原因。 ——Megan Wachs,博士,SiFive 工程师

9. 7 致谢 David Patterson 把这本书献给他的父母: ——给我的父亲 David,我从他那儿继承了创造 力、运动天赋和为正义奋斗的勇气;以及 ——给我的母亲 Lucy,我从她那儿继承了智慧、 乐观和良好的性格。 感谢你们成为我如此伟大的榜样,你们让我明 白了成为好的配偶、父亲和祖父的意义。

10.8 Andrew Waterman 把这本书献给他的父母 John 和 Elizabeth,他们即便在千里之外也支持着他。

11. 9 关于作者 David Patterson 在加州大学伯克利分校担任计算机科学教授 40 年后于 2016 年退休, 随后加入 Google 担任杰出工程师(distinguished engineer,Google 的职位) 。他还担任 了 RISC-V 基金会董事会副主席。过去,他曾被任命为伯克利计算机科学部(Computer Science Division)主席,并当选为计算机研究协会(Computing Research Association) 主席和计算机协会(ACM,Association for Computing Machinery)主席。在 20 世纪 80 年代,他领导了四代精简指令集计算机(RISC,Reduced Instruction Set Computer) 项目,伯克利最新的 RISC 因此得名“RISC Five”。他和 Andrew Waterman 都是 RISC- V 四位架构师中的一员。除了 RISC 以外,他最著名的研究项目有廉价磁盘冗余阵列 (RAID,Redundant Arrays of Inexpensive Disks)和工作站网络(NOW,Networks of Workstations) 。这项研究让他发表了许多论文,出版了 7 本书,获得了超过 35 个荣 誉,包括当选国家工程院和国家科学院院士,名列硅谷工程师名人堂,还成为了计算 机历史博物馆、ACM、IEEE 和两个 AAAS 组织的研究员。他的教学奖项包括杰出教 学奖(加州大学伯克利分校),Karstrom 杰出教育家奖(ACM) ,Mulligan 教育奖章 (IEEE)和本科教学奖(IEEE) 。他还因为一本计算机体系结构方面的书和一本关于 软件工程的书被文本和学术作家协会(Text and Academic Authors Association)授予计 算机教科书卓越奖( “Texty”)。他在加州大学洛杉矶分校获得了他的所有学位,也被 授予了杰出工程学院校友奖。他在南加州长大,乐趣是踢足球、和他的儿子一起骑自 行车,以及和妻子在沙滩上散步。他们在高中时期就是情侣。在本书的测试版出版几 天后,他们庆祝了 50 周年结婚纪念日。 Andrew Waterman 是 SiFive 的总工程师和联合创始人。SiFive 由 RISC-V 架构的创建 者们建立,旨在提供基于 RISC-V 的低成本定制芯片。他在加州大学伯克利分校获得 了计算机科学博士学位。在那里,他厌倦了现有的指令集架构的变幻莫测,于是共同 设计了 RISC-V ISA 和第一台 RISC-V 微处理器。 Andrew 是基于开源 RISC-V 的 Rocket 芯片生成器、Chisel 硬件构造语言以及 Linux 操作系统内核和 GNU C 编译器和 C 库 的 RISC-V 端口的主要贡献者之一。他还有加州大学伯克利分校的硕士学位,这是 RISC-V 的 RVC 扩展的基础,他还有杜克大学的工学学士学位。

12.10 前言 欢迎! RISC-V 自 2011 年推出以来迅速地普及。我们认为一个精简的程序员指南将进一步促进 它的发展,并促使新人理解为什么它是一个有吸引力的指令集,以及它与传统指令集架构 (ISA)的不同。 我们的灵感部分来源于其它指令集架构书籍,但我们希望 RISC-V 自身的简洁性能让我 们写得比 See MIPS Run 一类 500 多页的详尽书籍少很多。我们把全书的长度控制到了前述 的三分之一,至少在这个意义上我们成功了。实际上,介绍模块化 RISC-V 指令集的每个组 成部分的十章只用了 100 页——即便为了有助于快速阅读,平均每页用到了一张图片(一共 75 张)。 在解释指令集设计的原理之后,我们将阐述 RISC-V 架构师在设计指令集的时候,如何 在过去 40 年的指令集的基础上取其精华,去其糟粕。要评判一个指令集架构,不仅要看它 包括了什么,而且要看它省略了什么。 随后我们会按顺序介绍这个模块化架构的每个组成部分。每一章都会包含一个用 RISC- V 汇编语言写成的程序,这是为了展示那一章所述的指令的用法,这样有助于汇编语言程序 员学习 RISC-V 汇编。有时,我们还会列出用 ARM,MIPS 和 x86 写成的同样的程序,从而 突出 RISC-V 在简洁性,以及成本、功耗、性能方面的优势。 为了增加本书的趣味性,我们在页边加入了将近 50 个侧边栏,这里面放了一些有关书 中内容的评论,希望它们能带来一些乐趣。我们还在页边放了大约 75 个图片,用于展示设 计良好 ISA 的例子。 (我们充分利用了侧边的空间!)最后,对于那些愿意钻研的读者,我们 在全书中加入了大概 25 段补充说明。如果你对某个主题感兴趣,可以深入研究这些可选部 分。略过这些部分不会影响对书中的其他内容的理解,所以如果你对他们不感兴趣的话,尽 管跳过它们。对于计算机体系结构爱好者,我们援引的 25 篇论文和书籍能够开阔你的视野。 在写这本书的过程中,我们从它们当中学到了很多东西! 为什么引用了这么多名言? 我们认为引用这些名言也能增加本书的趣味性,因此我们把这 25 个引用分散在整本书 里。 它们同样是一种将智慧从前辈传递给初学者的有效机制,且有助于为良好的 ISA 设计 设定文化标准。我们希望读者也能了解一点该领域的历史,这就是为什么我们在全书中引用 了众多著名计算机科学家和工程师的名言。 导言和参考 我们打算将这本薄薄的书作为RISC-V的介绍和参考资料,供有兴趣编写RISC-V代码的 学生和嵌入式系统程序员使用。本书假设读者事先已经了解过至少一个指令集。如果没 有,您可能希望浏览基于RISC-V的相关入门架构手册:Computer Organization and Design RISC-V Edition: The Hardware Software Interface。 这本书中的参考资料包括: ⚫ 参考卡——这个一页(两面)的RISC-V的精简描述囊括了RV32GCV和 RV64GCV,同时包含了基本内容和所有已定义的指令扩展:RVI, RVM, RVA, RVF, RVD,甚至包括了尚处在开发阶段的RVV。 ⚫ 指令图——每个指令扩展的半页图形描述(它们是每章的第一个图)以同样的格 式列出了所有RISC-V指令的全称,让大家可以轻松查看每条指令的不同变种。见

13. 11 图2.1、4.1、5.1、6.1、7.1、8.1、9.1、9.2、9.3和9.4。 ⚫ 操作码映射——这些表格在一页中显示了指令布局,操作码,格式类型和每页指 令扩展的指令助记符。见图2.3、3.3、3.4、4.2、5.2、5.3、6.2、7.6、7.5、7.7、 9.5和10.1。 (这些指令图和操作码映射启发了我们在书的副标题中使用单词图 集。 ) ⚫ 指令术语表——附录A是对每个RISC-V指令和伪指令的详尽描述1。它包括所有内 容:操作名称和操作数、英文描述、寄存器传输语言定义、它所在的RISC-V扩 展、指令的全称、指令格式、显示操作码的指令图,以及紧凑版本指令的参照。 令人惊讶的是,所有这些加起来不到50页。 ⚫ 索引——它可以帮你通过指令全称或助记符找到描述指令说明、定义或图表的页 面。它是按照字典的形式组织的。 勘误和补充内容 我们打算把勘误集中起来,每年发布几次更新。这本书的网站上会有本书的最新版 本,还会简单介绍一下当前版本相对上一版本的改变。可在本书的网站 (www.riscvbook.com)上查看勘误表的历史版本或报告新的错误。我们预先为您在这一版 中发现的问题表示歉意。我们期待您的反馈意见,来帮助我们改进这本书。 本书的诞生过程 在2017年5月8日至11日在上海举行的第六届RISC-V研讨会上,我们认识到了对这么一 本书的需求,几个星期后我们开始了编写。考虑到Patterson在写书方面的丰富经验,我们 计划让他写大部分的章节。我们两人在组织方面进行了合作,并且是彼此章节的第一个评 论者。Patterson撰写了第1、2、3、4、5、6、7、8、9、11章,参考卡和本前言,而 Waterman写了第10章和附录A(本书的最大部分) ,并编写了书中的全部程序。Waterman还 维护了Armando Fox提供的LaTeX工具,使我们能做出这本书。 我们在2017年秋季学期为800名加州大学伯克利分校的学生提供了这本教科书的测试版 本。在融入了他们的反馈后,当2017年学期结束以后,第一个正式版将于2017年11月28日 至30日在硅谷举办的第七届RISC研讨会上及时发布。 RISC-V是一个伯克利研究项目的副产品。该项目正在针对更容易地同时构建硬件和软 件的目标进行开发。 致谢 我们要感谢Armando Fox,因为我们使用了他的LaTeX工具,以及采纳了他关于个人出 版的建议。 我们最深切的感谢要送给那些读了本书早期的草稿并提出了有用建议的人,比如: Krste Asanovi´c, Nikhil Athreya, C. Gordon Bell, Stuart Hoad, David Kanter, John Mashey, Ivan Sutherland, Ted Speers, Michael Taylor, Megan Wachs,…. 最后,我们要感谢数百名加州大学伯克利分校学生在调试方面的付出以及他们的对这 些素材的持续热忱! David Patterson 和 Andrew Waterman 2017年9月1日于加州伯克利 1定义 RV32V 的委员会没有赶在本书的测试版本之前完成他们的工作,所以我们在附录 A 中省略了这些 指令。尽管到时候 RV32V 有可能会有一些微小的改变,第八章是我们对于它的最为接近的猜想。

14.12 译者序 大约四个月前的一天,我收到加州大学伯克利分校毕业的谭章熹博士的消息,告知图 灵奖得主David Patterson教授(谭博士的导师)希望将他和Andrew Waterman一起完成的 《The RISC-V Reader》翻译成中文。这让我想起了大约四年前的一天,我收到了正在加州 大学伯克利分校做博士后的钱学海博士的邮件,告知David Patterson教授希望将他和Krste Asanovic教授一起撰写的文章在中文杂志上发表。当我收到了中文翻译稿《指令系统应该 免费:RISC-V的案例》后,动用了专栏编委的一点小权利,立刻向《中国计算机学会通 讯》强烈推荐了这篇文章。文章很快于2015年2月发表,然而略显遗憾的是彼时它并未得到 广泛关注,不过却让我们团队“近水楼台先得月”,成为国内最早将体系结构前沿研究全面 转到了RISC-V平台的团队。这一次,怀着对RISC-V的感激之情、对Patterson教授的敬仰之 心,更是为了便于更多中国爱好者了解RISC-V的愿望,我欣然接受了谭博士的请求。 过去几年深入接触RISC-V后,我心中时常呈现出一种愿景——RISC-V很可能像Linux 那样开启开源芯片设计的黄金时代。事实上,伯克利的科研侠客们发明RISC-V就是希望 “Instruction Sets Want to be Free”——全世界任何公司、大学、研究机构与个人都可以开 发兼容RISC-V指令集的处理器,都可以融入到基于RISC-V构建的软硬件生态系统,而不需 要为指令集付一分钱。这是伟大的理想! 在开源软件生态中,Linux是整个生态的基石。基于Linux,人们开发Python、LLVM、 GCC等完整的工具链,创造MySQL、Apache、Hadoop等大量开源软件,实验各种创新思想 与技术,逐渐形成一个价值超过150亿美元的开源软件生态。这对中国的互联网产业的意义 尤为重大,不仅提升了BAT等互联网企业的技术研发能力,也大大降低了互联网产业创新 的门槛,如今3-5位开发人员在几个月时间里就能快速开发出一个互联网应用。在芯片设计 领域,RISC-V有望像Linux那样成为计算机芯片与系统创新的基石。但是只有RISC-V又是 远远不够的,更重要的是要形成一个基于RISC-V的开源芯片设计生态,包括开源工具链、 开源IP、开源SoC等等。 RISC-V还只是星星之火,却已展露出燎原之潜力。作为全世界最大的芯片用户,中国 一直希望能把芯片产业做大做强,各方也都在努力。借鉴开源软件对于中国互联网产业发 展的作用,也许开源芯片设计是一条值得尝试的道路。这本中文版《RISC-V手册》 ,希望 能成为这条道路上一个小路标。 包云岗 2018 年 11 月 3 日 翻译团队  包云岗 中科院计算所研究员,先进计算机系统研究中心主任,长期从事计算机体系结构研究  勾凌睿 中国科学院大学计算机科学与技术专业本科生,有志于计算机体系结构研究  黄成 中科院计算所研究生,研究方向为计算机系统结构  刘志刚 中科院计算所硕士研究生,开展基于 RISC-V 的前沿研究,曾获第二届全国大学生计算机系统 能力培养大赛一等奖

15. 13 第一章 为什么要有 RISC-V? 简约是复杂的最终形式。 ——列奥纳多·达·芬奇(Leonardo da Vinci) 1.1 导言 RISC-V( “RISC five”)的目标是成为一个通用的指令集架构(ISA) : ⚫ 它要能适应包括从最袖珍的嵌入式控制器,到最快的高性能计算机等各种规模的 列奥纳多·达·芬奇 (1452-1519) 是 一位 文 处理器。 艺复兴时期的建筑师, 工程师,雕塑家,同时 ⚫ 它应该能兼容各种流行的软件栈和编程语言。 也是一名画家,创作了 ⚫ 它应该适应所有实现技术,包括现场可编程门阵列(FPGA) 、专用集成电路 著名的《蒙娜丽莎的微 笑》 (ASIC) 、全定制芯片,甚至未来的设备技术。 ⚫ 它应该对所有微体系结构样式都有效:例如微编码或硬连线控制;顺序或乱序执行 流水线; 单发射或超标量等等。 ⚫ 它应该支持广泛的专业化,成为定制加速器的基础,因为随着摩尔定律的消退, 加速器的重要性日益提高。 ⚫ 它应该是稳定的,基础的指令集架构不应该改变。更重要的是,它不能像以前的 专有指令集架构一样被弃用,例如AMD Am29000、Digital Alpha、Digital VAX、 Hewlett Packard PA-RISC、Intel i860、Intel i960、Motorola 88000、以及Zilog Z8000。 RISC-V的不同寻常不仅在于它是一个最近诞生的指令集架构(它诞生于最近十 年,而大多数其他指令集都诞生于20世纪70到80年代),而且在于它是一个开源的指 令集架构。与几乎所有的旧架构不同,它的未来不受任何单一公司的浮沉或一时兴起 的决定的影响(这一点让许多过去的指令集架构都遭了殃)。它属于一个开放的,非 营利性质的基金会。RISC-V基金会的目标是保持RISC-V的稳定性,仅仅出于技术原 因缓慢而谨慎地发展它,并力图让它之于硬件如同Linux之于操作系统一样受欢迎。 我们在页边加入了侧 图1.1列出了RISC-V基金会最大的企业成员,作为其活力的证明。 边栏,是希望能在里面 放入一些有意思的评 论。比如,RISC-V 最初 是为加州大学伯克利 分校的内部研究和课 程开发的。外部人员的 使用使它变得开放。 RISC-V 架构师在开始 收到有关网上 ISA 课程 变化的投诉时就了解 到了来自外部的兴趣。 只有在架构师理解了 需求之后,他们才会尝 试把它变为一个开放 图1.1:2017年5月第六届RISC-V研讨会上RISC-V基金会的企业成员按年销售额排名。左栏公 的 ISA 标准。 司的年销售额均超过500亿美元,中间栏目公司的销售额低于500亿美元但超过50亿美元,右栏 的销售额低于50亿美元但超过5亿美元。RISC-V基金会包括另外25家小公司,5家初创公司 (Antmicro Ltd,Blockstream,Esperanto Technologies,Greenwaves Technologies和SiFive), 4家非营利组织(CSEM,Draper Laboratory,ICT和lowRISC)和6所大学(ETH Zurich, IIT Madras,National University of Defense Technology,Princeton和UC Berkeley)。 60个组 织中的大多数总部都在美国以外。要了解更多信息,请访问www.riscv.org。

16.14 图1.2:x86指令集自诞生以来指令数量的增长。x86在1978年诞生时有80条指令,到2015年增长了16倍, 到了1338条指令,并且仍在增长。令人惊讶的是这张图的数据仍显保守。2015年在英特尔的博客上有着 3600条指令的统计结果[Rodgers and Uhlig 2017],这意味着x86指令的增长速率提高到了(在1978年到 2015年之内)每四天增长一条。我们是用汇编语言指令计算的,他们想必算入了机器语言指令。正如第八 章所解释的那样,这个增长的很大一部分是因为x86 ISA依赖于SIMD指令来实现数据级并行。 图1.3:x86-32 ASCII Adjust after Addition(aaa)指令的描述。它以二进制编码十进制数(BCD)形式 进行计算机运算,这种方式已经被扔进信息技术历史的垃圾堆里。x86还有三个相似的指令,分别执行减 法操作(aas),乘法操作(aam),和除法操作(aad)。由于他们都是单字节指令,它们加起来占用了宝 贵的操作码空间的1.6%(4/256)。 1.2 模块化与增量型 ISA 英特尔曾将其未来押在高端微处理器之上,但那时还需要很多年时间。为了对抗Zilog,英特尔开发了 一款过渡产品,并给它起名为8086。它本应该是短命的,没有任何继任者,但事情并非如此。高端处 理器姗姗来迟,等它最终出现时,它的性能并不如人意。因此,8086架构延续了下去——它变成32位 处理器,最终演变为了64位处理器。它的名称不断变化(80186,80286,i386,i486,Pentium) ,但基 础指令集保持不变。 ——Stephen P. Morse, 8086的架构师[Morse 2017]

17. 15 计算机体系结构的传统方法是增量ISA,新处理器不仅必须实现新的ISA扩展,还必须 实现过去的所有扩展。目的是为了保持向后的二进制兼容性,这样几十年前程序的二进制 版本仍然可以在最新的处理器上正确运行。这一要求与来自于同时发布新指令和新处理器 的营销上的诱惑共同导致了ISA的体量随时间大幅增长。例如,图1.2显示了当今主导ISA 80x86的指令数量增长过程。这个指令集架构的历史可以追溯到1978年,在它的漫长生涯 中,它平均每个月增加了大约三条指令。 这个传统意味着x86-32(我们用它表示32位地址版本的x86)的每个实现必须实现过去 的扩展中的错误设计,即便它们不再有意义。例如,图1.3描述了x86的ASCII Adjust after Addition(aaa)指令,该指令早已失效。 作为一个类比,假设一家餐馆只提供固定价格的餐点,最初只是一顿包含汉堡和奶昔 的小餐。随着时间的推移,它会加入薯条,然后是冰淇淋圣代,然后是沙拉,馅饼,葡萄 酒,素食意大利面,牛排,啤酒,无穷无尽,直到它成为一顿大餐。食客可以在那家餐厅 找到他们过去吃过的东西,尽管总的来说这样做可能没什么意义。这样做的坏处是,用餐 者为每次晚餐支付的宴会费用不断增加。 RISC-V的不同寻常之处,除了在于它是最近诞生的和开源的以外,还在于:和几乎所 有以往的ISA不同,它是模块化的。它的核心是一个名为RV32I的基础ISA,运行一个完整 如果软件使用来自可 选扩展的省略的 RISC- 的软件栈。RV32I是固定的,永远不会改变。这为编译器编写者,操作系统开发人员和汇 V 指令,则硬件会在软 编语言程序员提供了稳定的目标。模块化来源于可选的标准扩展,根据应用程序的需要, 件中捕获并执行所需 的功能,作为标准库的 硬件可以包含或不包含这些扩展。这种模块化特性使得RISC-V具有了袖珍化、低能耗的特 一部分。 点,而这对于嵌入式应用可能至关重要。RISC-V编译器得知当前硬件包含哪些扩展后,便 可以生成当前硬件条件下的最佳代码。惯例是把代表扩展的字母附加到指令集名称之后作 为指示。例如,RV32IMFD将乘法(RV32M),单精度浮点(RV32F)和双精度浮点 (RV32D)的扩展添加到了基础指令集(RV32I)中。 继续用我们刚才的类比来说,RISC-V提供的是菜单,而不是一顿应有尽有的自助餐。 主厨只需要烹饪顾客需要的东西(而不是每次都做出一顿盛宴),顾客只需要按他们的订单 付费。RISC-V无需仅仅为了市场吸引力而添加指令。RISC-V基金会会决定什么时候在菜单 里添加新的选项,而他们只会出于技术原因这样做,而且要在由软硬件专家组成的委员会 进行专门的公开讨论以后才会添加。即使那些新选择出现在了菜单上,它们仍是可选的, 不会像在增量ISA中那样成为未来所有实现的必要组成部分。 1.3 ISA 设计 101 在介绍 RISC-V 这个 ISA 之前,了解计算机架构师在设计 ISA 时的基本原则和必须做 出的权衡是有用的。如下的列表列出了七种衡量标准。页边放置了对应的七个图标,以突 出显示 RISC-V 在随后章节中应对它们的实例。(印刷版的封底有所有图标的图例。 ) ⚫ 成本(美元硬币) ⚫ 简洁性(轮子) ⚫ 性能(速度计) ⚫ 架构和具体实现的分离(分开的两个半圆) ⚫ 提升空间(手风琴) ⚫ 程序大小(相对的压迫着一条线的两个箭头) ⚫ 易于编程/编译/链接(儿童积木“像 ABC 一样简单” ) 为了解释我们的意思,在这一节中我们会展示一些以往 ISA 所作出的选择。它们现在

18.16 看起来是不明智的,而 RISC-V 通常会做出更好的决定。 成本 处理器通过集成电路实现,通常称为芯片或晶粒。它们叫做晶粒是因为,它们由一些 单个的圆形晶片被切割成许多单独的片得到。图 1.4 显示了 RISC-V 处理器的晶圆。成本对 晶粒面积十分敏感: cost ≈ f(die area2) 显然,晶粒越小,每个晶圆上能切割出来的晶粒越多。晶粒的大部分成本来自于处理过 的晶圆本身。不太直观的是,晶粒越小,产率(生产出的可用晶粒所占的比例)越高。原因 在于目前的硅生产工艺会在晶圆上留下一些散布的小瑕疵。因此晶粒越小,有缺陷部分所占 比重会越低。 图1.4:由SiFive设计的直径为8英寸的RISC-V晶圆。 它有两种类型的RISC-V芯片,使用较旧的较大加工 线。 FE310芯片为2.65mm×2.72mm,SiFive测试芯片为2.89mm×2.72mm。 一片晶圆上有1846片FE310和 1866片SiFive测试芯片,总共3712个芯片。 架构师希望保持 ISA 的简洁性,从而缩小实现 ISA 的处理器的尺寸。我们将在随后的 章节看到,RISC-V ISA 比 ARM-32 ISA 简洁得多。就简洁性造成的影响举例,我们把使用 相同大小缓存(16KiB)的 RISC-V Rocket 处理器和采用相同技术(TSMC40GPLUS)的 ARM- 32 Cortex A5 处理器进行比较。RISC-V 晶粒的大小是 0.27mm2,而 ARM-32 晶粒的大小是 0.53mm2。由于面积大一倍,ARM-32 Cortex A5 的晶粒成本是 RISC-V Rocket 的约 4(22) 高端处理器可以通过 将简单的指令组合在 倍。即使晶粒的大小只缩小 10%,成本也将以 1.2(1.12)倍的比例缩小。 一起来提升性能,而不 会因更大,更复杂的 ISA 给所有低端实现带 简洁性 鉴于成本对于复杂度的敏感性,架构师需要一个简单的 ISA 来缩小芯片面积。ISA 来负担。这种技术称为 宏观融合,因为它将 的简洁性还能缩短芯片的设计和验证时间,而它们可能构成了芯片开发的大部分成本。这些 “宏”指令融合在一 成本必须算到芯片的成本当中。这个开销取决于发货芯片的数量。简洁性还能降低文档成本, 起。

19. 17 让客户更容易了解如何使用这个 ISA。 以下是 ARM-32 的 ISA 复杂性的一个明显示例: ldmiaeq SP!, {R4-R7, PC} 该指令代表 LoaD Multiple, Increment-Address, on EQual。它执行 5 次数据加载并写入 6 个寄存器,但仅当 EQ 条件码置位时才执行。此外,它将结果写入 PC,因此它也执行条件 分支。真不少! 简单的处理器对嵌入 具有讽刺意味的是,即便需要实现的功能相同,简单指令也通常比复杂指令更容易被用 式应用程序有益,因为 到。例如,x86-32 有一个 enter 指令,该指令本应该是在进入一个创建一个栈帧的过程中执 它更容易预测执行时 间。微控制器的汇编语 行的第一条指令(见第三章) 。大多数编译器用两条简单的 x86-32 指令来代替它: 言程序员通常希望保 push ebp # 将帧指针压入栈 持精确的时序,因此他 们会保持代码执行所 mov ebp, esp # 把栈指针复制到帧指针 需的时钟周期数可预 测并可以手动数出来。 性能 除非是那些用于嵌入式应用的微型芯片,处理器的性能和成本通常都能成为架构师的 关注对象。性能可以分解为如下三个因素: 𝑖𝑛𝑠𝑡𝑟𝑢𝑐𝑡𝑖𝑜𝑛𝑠 𝑎𝑣𝑒𝑟𝑎𝑔𝑒 𝑐𝑙𝑜𝑐𝑘 𝑐𝑦𝑐𝑙𝑒𝑠 𝑡𝑖𝑚𝑒 𝑡𝑖𝑚𝑒 最后一个因素是时钟 × × = 频率的倒数,因此 1 𝑝𝑟𝑜𝑔𝑟𝑎𝑚 𝑖𝑛𝑠𝑡𝑟𝑢𝑐𝑡𝑖𝑜𝑛 𝑐𝑙𝑜𝑐𝑘 𝑐𝑦𝑐𝑙𝑒 𝑝𝑟𝑜𝑔𝑟𝑎𝑚 GHz 时钟频率意味着每 个时钟周期的时间为 1 即使一个简单的 ISA 可能在每个程序执行的指令数方面多于复杂的 ISA,但它可以通过 更快的时钟频率或更低的平均单条指令周期数(CPI)来弥补。 9 ns(1 / 10 )。 例如,运行 CoreMark 测试程序[Gal-On, Levy 2012](100000 次迭代)后,得到 ARM-32 Cortex-A9 的性能为: 32.27 𝐵 𝑖𝑛𝑠𝑡𝑟𝑢𝑐𝑡𝑖𝑜𝑛𝑠 0.79 𝑐𝑙𝑜𝑐𝑘 𝑐𝑦𝑐𝑙𝑒𝑠 0.71 𝑛𝑠 18.15 𝑠𝑒𝑐𝑠 × × = 𝑝𝑟𝑜𝑔𝑟𝑎𝑚 𝑖𝑛𝑠𝑡𝑟𝑢𝑐𝑡𝑖𝑜𝑛 𝑐𝑙𝑜𝑐𝑘 𝑐𝑦𝑐𝑙𝑒 𝑝𝑟𝑜𝑔𝑟𝑎𝑚 平均时钟周期数可以 小于 1, 因为 A9 和 BOOM 对应地,RISC-V 的 BOOM 实现的性能为: [Celio et al.2015]是 29.51 𝐵 𝑖𝑛𝑠𝑡𝑟𝑢𝑐𝑡𝑖𝑜𝑛𝑠 0.72 𝑐𝑙𝑜𝑐𝑘 𝑐𝑦𝑐𝑙𝑒𝑠 0.67 𝑛𝑠 14.26 𝑠𝑒𝑐𝑠 所谓的超标量处理器, × × = 每个时钟周期执行多 𝑝𝑟𝑜𝑔𝑟𝑎𝑚 𝑖𝑛𝑠𝑡𝑟𝑢𝑐𝑡𝑖𝑜𝑛 𝑐𝑙𝑜𝑐𝑘 𝑐𝑦𝑐𝑙𝑒 𝑝𝑟𝑜𝑔𝑟𝑎𝑚 个指令。 在这个例子中,ARM 处理器执行的指令并不比 RISC-V 处理器少。正如我们将要看到 的,简单的指令也是最常用到的指令,因此 ISA 的简洁性是最为重要的指标。对于这个程 序,RISC-V 处理器在这三个因素中的每一个都获得了近 10%的优势,它们加起来导致了近 30%的性能优势。如果更简洁的 ISA 也能催生出更小的芯片,那么其性价比将非常出色。 架构和具体实现的分离 架构和实现之间最初的分离可以追溯到 20 世纪 60 年代,具体表现 为:机器语言程序员了解架构后能写出正确的程序,却不一定能保证性能。对于架构师来说, 为了在性能和成本上对某一特定时间的某种实现进行优化,而在 ISA 中包含某些指令,有时 候是一件有诱惑性的事情。但这样做会给其他实现或者今后的实现带来负担。 延迟分支是 MIPS-32 ISA 的一个令人遗憾的例子。条件分支导致流水线执行出现问题, 因为处理器希望下一条要执行的指令总是已经在流水线上,但它不能确定它要的到底是顺序 执行的下一条(如果分支未执行),还是分支目标地址的那一条(如果执行了分支) 。对于它 今天的流水线处理器 使用硬件预测器预测 们的第一个五级流水的微处理器,这种优柔寡断可能导致流水线一个时钟周期的阻塞。 分支结果,这种方法的 MIPS-32 通过把分支操作重新定义在分支指令的下一条指令执行完之后发生,因此分支指令 准确度可以超过 90%, 并且适用于任何大小 的下一条指令永远会被执行。程序员或编译器编写者要做的是把一些有用的指令放入延迟槽。 的流水线。他们只需要 唉,这个“解决方案”对接下来有着更多流水级(于是在计算出分支结果之前取了更多 一种机制来刷新和重 启流水线。 的指令)的 MIPS-32 处理器并无益处,反而让 MIPS-32 程序员,编译器编写者,以及处理 器设计者(因为增量 ISA 需要向后兼容,见 1.2 节)的生活变得更加艰难。此外,它让 MIPS-

20.18 32 的代码变得更加难懂(参见第 29 页图 2.10)。 虽然架构师不该为了有助于某个时间点的某一个特定实现而特意加入某些功能,但他们 也不应该放入阻碍某些实现的功能。例如,如上一页所述,ARM-32 和其他一些 ISA 具有 Load Multiple 指令。这些指令可以提高单发射流水线设计的性能,但会降低多发射流水线的 效率。原因在于这种直截了当的实现排除了与其他指令并行地调度 Load Multiple 的各个负 载的可能,从而降低了这些处理器的指令吞吐量。 提升空间 随着摩尔定律(Moore’s law)的终结,对性价比进行重大改进的唯一途径是为特 定领域(例如深度学习,增强现实,组合优化,图形等)添加自定义指令。这意味着如今的 ISA 必须保留操作码空间以供未来的提升。 在 20 世纪 70 年代和 80 年代,当摩尔定律如日中天的时候,很少有人考虑为未来的提 升节省操作码空间。相反,架构师们重视长地址和立即数字段以减少每个程序执行的指令数 (这是前一页上有关性能的方程式中的第一个因素) 。 一个能说明缺少操作码空间的弊端的例子是,ARM-32 的架构师后来试图通过向以前统 上面提到的 ARM-32 指 一的 32 位 ISA 中添加 16 位指令来缩减代码长度,但根本就没有空间了。因此,唯一的解决 令 ldmiaeq 甚至更复 杂,因为当它分支时它 方案是先用 16 位指令来创建一个新的 ISA(Thumb),然后同时用 16 位指令和 32 位指令来 也 可 以 将 ARM-32 从 Thumb/Thumb-2 两种模 组成另外一个 ISA(Thumb-2) ,并用一个模式位在两种长度的指令间切换。为了切换模式, 式中切换。 程序员或编译器会跳转到一个最低有效位为 1 的字节地址。这种方法有效的前提是,在正常 的 16 位和 32 位指令中,该位应该是 0。 图1.5:RV32G,ARM-32,x86-32,RV32C和Thumb-2程序的相对大小。最后两个ISA是以短代码长度为 目标的。 这些程序是使用GCC编译器的SPEC CPU2006基准测试。与RV32C相比,Thumb-2的代码短小 的优势是由于在进入程序时Load and Store Multiple的节省。RV32C没有包含它们,以保持与RV32G指令 的一对一映射,RV32G省略了Load and Store Multiple以降低高端处理器的实现复杂性(见下文)。第七 章介绍了RV32C。RV32G表示RISC-V扩展(RV32M,RV32F,RV32D和RV32A)的流行组合,正确称 为RV32IMAFD。[Waterman 2016] 程序大小 程序越小,存储它所需的芯片面积就越小(这对于嵌入式设备来说可能是一个巨大 的成本)。实际上,这个问题促使 ARM 架构师在 Thumb 和 Thumb-2 ISA 中追加了一些更短 的指令。更小的程序还能减少指令缓存的未命中问题,从而节省了功耗(因为片外 DRAM 访问比片上 SRAM 访问耗能更多),也提高了性能。短的代码长度是 ISA 架构师的目标之 一。

21. 19 x86-32 ISA 的指令可以短至 1 字节,也可以长达 15 字节。你可能会觉得 x86 的这种可 变字节长度的指令写成的程序一定会比用一些 ISA(比如 ARM-32,RISC-V)中 32 位定长 指令写的要更短。逻辑上,可变字节长度指令的程序也应该小于仅由 16 位和 32 位定长指令 例 如 一 个 15 字 节 的 x86-32 指 令 是 lock 组成的 ISA(比如 Thumb-2 和使用 RV32C 扩展的 RISC-V,参见第七章) 。图 1.5 显示,当 add dword ptr ds: [esi+ecx*4+0x1234 所有指令都是 32 位长时, ARM-32 和 RISC-V 代码比 x86-32 长 6%到 9%, 而令人惊讶的是, 5678],0xefcdab89。 x86-32 代码比同时提供 16 位和 32 位指令的压缩版本(Thumb-2 和 RV32C)大 26%。 它汇编成(十六进制) : 67 66 f0 3e 81 84 8e 虽然使用新的可变字节长度指令的新 ISA 可能会导致比 RV32C 和 Thumb-2 更短的代 78 56 34 12 89 ab cd 码,但 20 世纪 70 年代设计第一个 x86 的架构师并不关心这个问题。此外,考虑到增量 ISA ef。 最后 8 个字节是 2 个地址,前 7 个字节指 (第 1.2 节)对于向后二进制兼容性的要求,数百条新的 x86-32 指令比预期要长。它们有着 定原子的存储器操作, 一到两个字节长前缀的负担,这迫使它们使用原始 x86 的有限的空余操作码空间。 加操作,32 位数据,数 据段寄存器,2 个地址 寄存器和缩放索引寻 易于编程/编译/链接 由于寄存器中的数据访问起来要比存储器中的快得多,编译器在寄存 址模式。 1 字节指令的 例子是汇编成 40 的指 器分配方面一定要做得很好。这件事在有许多寄存器的时候变得更加容易。鉴于这一点, 令 inc eax。 ARM-32 有 16 个寄存器,而 x86-32 只有 8 个。大多数现代 ISA(包括 RISC-V)都有 32 个 整型寄存器。毫无疑问,有了更多的寄存器,编译器和汇编程序员的工作会更加轻松。 编译器和汇编语言程序员的另一个问题是弄清楚一个代码序列的执行速度。我们可以看 到,一般每条 RISC-V 指令最多用一个时钟周期执行(忽略缓存未命中)。但正如我们之前 看到的,ARM-32 和 x86-32 都有需要很多个时钟周期执行(即使所有缓存都命中)的指令。 此外,与 ARM-32 和 RISC-V 不同,x86-32 的算术指令操作数可以在存储器中,而不必都在 寄存器里。复杂的指令和位于存储器中的操作数使得处理器的设计人员难以保证性能的可预 测性。 ISA 支持位置无关代码(PIC)非常有用,因为这样它就支持动态链接(参见第 3.5 节) , 原因在于在不同程序中共享库代码可以驻留在不同地址。PC 相关的分支和数据寻址是 PIC 的福音。虽然几乎所有的 ISA 都提供与 PC 相关的分支,但 x86-32 和 MIPS-32 省略了与 PC 相关的数据寻址。 补充说明:ARM-32,MIPS-32 和 x86-32 这是一个可选部分,如果对某个主题感兴趣的话,读者可以深入研究它们,但它们对于理解 本书的其余部分并不必要。例如,我们对于 ISA 的称呼不是官方名称。32 位地址 ARM ISA 有许多版本,第一个诞生于 1986 年,最新版本在 2005 年出现,称为 ARMv7。ARM-32 通 常是指 ARMv7 ISA。MIPS 也有许多 32 位版本,但我们指的是原版,称为 MIPS I(“MIPS32” 是一个更新的, 不同于我们称之为 MIPS-32 的 ISA)。 英特尔的第一个 16 位地址架构是 1978 年的 8086,其中 80386 ISA 在 1985 年扩展到 32 位地址。我们的 x86-32 表示法通常是指 IA- 32,它的 x86 ISA 的 32 位地址版本。鉴于这些 ISA 的数不清的变体的存在,我们发现我们 的非标准术语反而最不容易混淆。 1.4 全书的总览 本书假设您在 RISC-V 之前已经了解过其他指令集。如果没有,请查看我们基于 RISC-V 的相关入门架构书[Patterson 和 Hennessy 2017]。 第二章介绍了 RV32I,它是 RISC-V 固定不变的基础整数指令集,是 RISC-V 的核心内 容。第三章解释了第二章中没有介绍的其余 RISC-V 汇编语言内容,包括调用约定和一些

22.20 用于链接的巧妙技巧。汇编语言包括所有符合规则的 RISC-V 指令和一些 RISC-V 指令集外 的有用指令。这些伪指令是实际指令的巧妙变体,它们简化了编写汇编语言程序的过程, 同时避免了使 ISA 复杂化。 接下来的三章阐述了 RISC-V 的标准扩展。当它们添加到 RIV32I 中的时候,我们统称 RV32G(G 代表一般) : ⚫ 第四章:乘法和除法(RV32M) 参考卡也被称为绿色 ⚫ 第五章:浮点操作(RV32F 和 RV32D) 卡片,这来源于 20 世纪 60 年代的 ISA 的单页纸 ⚫ 第六章:原子操作(RV32A) 板摘要的背景颜色的 阴影。为了易读性,我 第 3 页和第 4 页的 RISC-V“参考卡”是本书中所有 RISC-V 指令(RV32G,RV64G 和 们将背景保持白色,而 RV32 / 64V)的摘要。 不是延续历史而使其 为绿色。 第七章介绍了可选的压缩扩展 RV32C,它是 RISC-V 优雅性的一个绝佳例子。通过把 16 位指令限制为现有 32 位 RV32G 指令的短版本,它们几乎是没有代价的。汇编程序可以 选择指令大小,这使得汇编语言程序员和编译器忘记 RV32C。将 16 位 RV32C 指令转换成 32 位 RV32G 指令的硬件解码器只需要 400 个门,这即使在最简单的 RISC-V 实现中也只占 百分之几。 第八章介绍了向量扩展 RV32V。当与众多强大的单指令多数据(SIMD)指令(ARM- 32,MIPS-32,x86-32)相比时,向量指令成为了 ISA 优雅性的另一个例证。实际上,图 1.2 中添加到 x86-32 的数百条指令都是 SIMD,还有数百条指令即将问世。RV32V 甚至比 大多数向量 ISA 更简单,因为它通过向量寄存器指定数据类型和长度,而不是将这两者嵌 入到操作码中。RV32V 也许是大家从传统的基于 SIMD 的 ISA 转到 RISC-V 的最为可能的 原因。 第九章展示了 RV64G,它是 RISC-V 的 64 位地址版本。正如该章节所说的那样, RISC-V 的架构师只需要拓宽寄存器,并加入一些字、双字或长版的 RV32G 指令,就可以 把地址从 32 位扩展为 64 位。 第十章介绍了系统指令,说明了 RISC-V 如何处理分页以及机器、用户和监管者权限 模式。 最后一章简要介绍了 RISC-V 基金会目前正在考虑增加的其它扩展。 接下来是本书最大的一个部分,附录 A。它是按字母表顺序排列的指令集摘要。它定 义了完整的 RISC-V ISA 以及上面提到的所有扩展,还有大概 50 页的全部伪指令。这是 RISC-V 简洁性的证明。 这本书的最后一部分是索引。 冯·诺伊曼先前版本的 精心编写的报告非常 1.5 结束语 有影响力,以至于这种 计算机通常被称为 冯·诺伊曼架构,尽管 这份报告是基于其他 用形式逻辑的方法可以很容易看出,存在某种[指令集]在理论上足以控制和执行任意顺序的操作…… 人的工作。它是在第一 从当前的观点出发,选择一个[指令集]时考虑得更多更实际的问题是:[指令集]要求的设备简单性, 台存储程序计算机开 始运行的三年前编写 在实际重要的问题中有明确应用和解决该类问题的速度。 的! ——冯·诺伊曼(von Neumann)等,1947 RISC-V 是一个最新的,清晰的,简约的,开源的 ISA,它以过去 ISA 所犯过的错误为 鉴。RISC-V 架构师的目标是让它在从最小的到最快的所有计算设备上都能有效工作。遵循 冯诺依曼 70 年前的建议,这个 ISA 强调简洁性来保证它的低成本,同时有着大量的寄存 器和透明的指令执行速度,从而帮助编译器和汇编语言程序员将实际的重要问题转换为适

23. 21 当的高效代码。 图1.6:ISA手册的页数和字数来自[Waterman and Asanovi'c 2017a],[Waterman and Asanovi'c 2017b], [Intel Corporation 2016],[ARM Ltd. 2014]。读完需要的时间按每分钟读200个单词,每周读40小时计 算。 基于[Baumann 2017]的图1的一部分。 复杂度的一个标准是文档的大小。图 1.6 显示了以页数和单词数衡量的 RISC-V、 ARM-32 和 x86-32 指令集手册的大小。如果你把读手册作为全职工作,每天 8 小时,每周 5 天,那么需要半个月读完 ARM-32 手册,需要整整一个月读完 x86-32 手册。有这样的复 杂程度,大概没有一个人能完全理解 ARM-32 或 x86-32。用这种常识来度量,RISC-V 的 1 1 1 复杂度只有 ARM-32 的 ,x86-32 的 到 。实际上,包含所有扩展的 RISC-V ISA 摘要只有 12 10 30 两页(参见参考卡) 。 这个袖珍的,开源的 ISA 于 2011 年推出,现在由一个基金会提供支持。该基金会通过 长期讨论后严格依据技术理由添加可选扩展的方式来改进它。开源性让 RISC-V 的免费 的、共享的实现成为可能,从而降低了成本,也减少了将不为人知的邪恶秘密隐藏在处理 器之中的可能性。 然而,只有硬件不能组成一个系统。软件开发成本可能使硬件开发成本相形见绌。因 此虽然稳定的硬件很重要,但稳定的软件更甚于此。这些软件需要包括操作系统,引导加 载程序,参考软件和大众化的软件工具。基金会保证整个 ISA 的稳定性,而固定不变的基 础指令集意味着核心的 RV32I 作为软件栈的目标永远不会改变。通过它的普适性和开源 性,RISC-V 可以挑战主流专有 ISA 的主导地位。 优雅是一个很少应用于 ISA 的词,但在阅读本书后,你可能会同意我们把它用于 RISC-V。我们将用页边的蒙娜丽莎图标来凸显我们认为体现出优雅性的特征。 1.6 扩展阅读 ARM Ltd. ARM Architecture Reference Manual: ARMv7-A and ARMv7-R Edition, 2014. URL http://infocenter.arm.com/help/topic/com.arm.doc.ddi0406c/. A. Baumann. Hardware is the new software. In Proceedings of the 16th Workshop on Hot Topics in Operating Systems, pages 132–137. ACM, 2017. C. Celio, D. Patterson, and K. Asanovic. The Berkeley Out-of-Order Machine (BOOM): an industry-competitive, synthesizable, parameterized RISC-V processor. Tech. Rep. UCB/EECS- 2015–167, EECS Department, University of California, Berkeley, 2015. S. Gal-On and M. Levy. Exploring CoreMark - a benchmark maximizing simplicity and efficacy. The Embedded Microprocessor Benchmark Consortium, 2012. Intel Corporation. Intel 64 and IA-32 Architectures Software Developer’s Manual, Volume 2: Instruction Set Reference. September 2016.

24.22 S. P. Morse. The Intel 8086 chip and the future of microprocessor design. Computer, 50(4): 8–9, 2017. D. A. Patterson and J. L. Hennessy. Computer Organization and Design RISC-V Edition: The Hardware Software Interface. Morgan Kaufmann, 2017. S. Rodgers and R. Uhlig. X86: Approaching 40 and still going strong, 2017. J. L. von Neumann, A.W. Burks, and H. H. Goldstine. Preliminary discussion of the logical design of an electronic computing instrument. Report to the U.S. Army Ordnance Department, 1947. A. Waterman. Design of the RISC-V Instruction Set Architecture. PhD thesis, EECS Department, University of California, Berkeley, Jan 2016. URL http://www2.eecs.berkeley.edu/Pubs/TechRpts/2016/EECS-2016-1.html. A. Waterman and K. Asanovi´c, editors. The RISC-V Instruction Set Manual Volume II: Privileged Architecture Version 1.10. May 2017a. URL https://riscv.org/specifications/privileged- isa/. A. Waterman and K. Asanovi´c, editors. The RISC-V Instruction Set Manual, Volume I: User- Level ISA, Version 2.2. May 2017b. URL https://riscv.org/specifications/. 注记 http://parlab.eecs.berkeley.edu

25. 23 第二章 RV32I:RISC-V 基础整数指令集 …提升计算性能并且让用户能切实享受到性能提升的唯一方法是同时设计编译器和计算机。这样软件用不 到的特性将不会被实现在硬件上… (1932-)被授予图灵 奖主要是因为她在 ——Frances Elizabeth “Fran” Allen, 1981 优化编译器方面的 工作。图灵奖是计 算机科学的最高奖 项。 2.1 导言 图 2.1 是 RV32I 基础指令集的一页图形表示。对于每幅图,将有下划线的字母从左到 右连接起来,即可组成完整的 RV32I 指令集。对于每一个图,集合标志{}内列举了指令的 所有变体,变体用加下划线的字母或下划线字符_表示。特别的,下划线字符_表示对于此 指令变体不需用字符表示。例如,下图表示了这四个 RV32I 指令:slt,slti,sltu,sltiu: 我们使用这些图(下面几章的第一个图),旨在对本章的指令给出一个进行快速、深入的 概述。 2.2 RV32I 指令格式 图 2.2 显示了六种基本指令格式,分别是:用于寄存器-寄存器操作的 R 类型指令,用 于短立即数和访存 load 操作的 I 型指令,用于访存 store 操作的 S 型指令,用于条件跳转操 作的 B 类型指令,用于长立即数的 U 型指令和用于无条件跳转的 J 型指令。图 2.3 使用图 2.2 的指令格式列出了图 2.1 中出现的所有 RV32I 指令的操作码。 即使是指令格式也能从一些方面说明 RISC-V 更简洁的 ISA 设计能提高提高性能功耗 比。首先,指令只有六种格式,并且所有的指令都是 32 位长,这简化了指令解码。ARM- 32,还有更典型的 x86-32 都有许多不同的指令格式,使得解码部件在低端实现中偏昂贵, 在中高端处理器设计中容易带来性能挑战。第二,RISC-V 指令提供三个寄存器操作数,而 立即数的符号扩展甚至 不是像 x86-32 一样,让源操作数和目的操作数共享一个字段。当一个操作天然就需要有三 有助于逻辑指令。例如, x&0xfffffff0 在 RISC-V 个不同的操作数,但是 ISA 只提供了两个操作数时,编译器或者汇编程序程序员就需要多 中只需要一条 andi 指 使用一条 move(搬运)指令,来保存目的寄存器的值。第三,在 RISC-V 中对于所有指 令,但在 MIPS-32 中需 要两条指令(addiu 用 令,要读写的寄存器的标识符总是在同一位置,意味着在解码指令之前,就可以先开始访 于加载常量,然后是 and),因为 MIPS 零扩 问寄存器。在许多其他的 ISA 中,某些指令字段在部分指令中被重用作为源目的地,在其 展逻辑立即数。ARM-32 他指令中又被作为目的操作数(例如,ARM-32 和 MIPS-32)。因此,为了取出正确的指 需要添加一个额外的指 令 bic , 它 执 行 rx & 令字段,我们需要时序本就可能紧张的解码路径上添加额外的解码逻辑,使得解码路径的 immediate 以补偿零扩 时序更为紧张。第四,这些格式的立即数字段总是符号扩展,符号位总是在指令中最高 展的立即数. 位。这意味着可能成为关键路径的立即数符号扩展,可以在指令解码之前进行。

26.24 图 2.1:RV32I 指令图示。把带下划线的字母从左到右连接就组成了 RV32I 指令。花括号{}表示集合中垂 直方向上的每个项目都是指令的不同变体。集合中的下划线_意味着不包含这个字母的也是一个指令名 称。例如,左上角附近的符号表示以下六个指令:and,or,xor,andi,ori,xori。 图 2.2:RISC-V 指令格式。我们用生成的立即数值中的位置(而不是通常的指令立即数域中的位置) (imm[x])标记每个立即数子域。第十章解释了控制状态寄存器指令使用 I 型格式的稍微不同的做法。 (本 图基于 Waterman 和 Asanovi'c 2017 的图 2.2)。

27. 25 31 25 24 20 19 15 14 12 11 76 0 imm[31:12] rd 0110111 U lui imm[31:12] rd 0010111 U auipc imm[20|10:1|11|19:12] rd 1101111 J jal imm[11:0] rs1 000 rd 1100111 I jalr imm[12|10:5] rs2 rs1 000 imm[4:1|11] 1100011 B beq imm[12|10:5] rs2 rs1 001 imm[4:1|11] 1100011 B bne imm[12|10:5] rs2 rs1 100 imm[4:1|11] 1100011 B blt imm[12|10:5] rs2 rs1 101 imm[4:1|11] 1100011 B bge imm[12|10:5] rs2 rs1 110 imm[4:1|11] 1100011 B bltu imm[12|10:5] rs2 rs1 111 imm[4:1|11] 1100011 B bgeu imm[11:0] rs1 000 rd 0000011 I lb imm[11:0] rs1 001 rd 0000011 I lh imm[11:0] rs1 010 rd 0000011 I lw imm[11:0] rs1 100 rd 0000011 I lbu imm[11:0] rs1 101 rd 0000011 I lhu imm[11:5] rs2 rs1 000 imm[4:0] 0100011 S sb imm[11:5] rs2 rs1 001 imm[4:0] 0100011 S sh imm[11:5] rs2 rs1 010 imm[4:0] 0100011 S sw imm[11:0] rs1 000 rd 0010011 I addi imm[11:0] rs1 010 rd 0010011 I slti imm[11:0] rs1 011 rd 0010011 I sltiu imm[11:0] rs1 100 rd 0010011 I xori imm[11:0] rs1 110 rd 0010011 I ori imm[11:0] rs1 111 rd 0010011 I andi 0000000 shamt rs1 001 rd 0010011 I slli 0000000 shamt rs1 101 rd 0010011 I srli 0100000 shamt rs1 101 rd 0010011 I srai 0000000 rs2 rs1 000 rd 0110011 R add 0100000 rs2 rs1 000 rd 0110011 R sub 0000000 rs2 rs1 001 rd 0110011 R sll 0000000 rs2 rs1 010 rd 0110011 R slt 0000000 rs2 rs1 011 rd 0110011 Rsltu 0000000 rs2 rs1 100 rd 0110011 R xor 0000000 rs2 rs1 101 rd 0110011 R srl 0100000 rs2 rs1 101 rd 0110011 R sra 0000000 rs2 rs1 110 rd 0110011 R or 0000000 rs2 rs1 111 rd 0110011 R and 0000 pred succ 00000 000 00000 0001111 I fence 0000 0000 0000 00000 001 00000 0001111 I fence.i 000000000000 00000 00 00000 1110011 I ecall 000000000000 00000 000 00000 1110011 I ebreak csr rs1 001 rd 1110011 I csrrw csr rs1 010 rd 1110011 I csrrs csr rs1 011 rd 1110011 I csrrc csr zimm 101 rd 1110011 I csrrwi csr zimm 110 rd 1110011 I cssrrsi csr zimm 111 rd 1110011 I csrrci 图 2.3:RV32I 带有指令布局,操作码,格式类型和名称的操作码映射。 (此图基于[Waterman and Asanovi'c 2017]的表 19.2。 )

28.26 补充说明:B 类型和 J 类型指令 如下所述,分支指令(B 类型)的立即数字段在 S 类型的基础上旋转了 1 位。跳转指令(J 类型)的直接字段在 U 类型的基础上旋转了 12 位。因此,RISC-V 实际上只有四种基本格式, 但我们可以保守地认为它有六种格式。 为了帮助程序员,所有位全部是 0 是非法的 RV32I 指令。因此, 试图跳转到被清零的 内存区域的错误跳转将会立即触发异常,这可以帮助调试。类似地,所有位全部是 1 的指 令也是非法指令,它将捕获其他常见的错误,诸如未编程的非易失性内存设备、断开连接 的内存总线或者坏掉的内存芯片。 为了给 ISA 扩展留出足够的空间,最基础的 RV32I 指令集只使用了 32 位指令字中的 编码空间的不到八分之一。架构师们也仔细挑选了 RV32I 操作码,使拥有共同数据通路的 指令的操作码位有尽可能多的位的值是一样的,这简化了控制逻辑。最后,当我们看到,B 和 J 格式的分支和跳转地址必须向左移动 1 位以将地址乘以 2,从而给予分支和跳转指令 更大的跳转范围。RISC-V 将立即数中的位从自然排布进行了一些移位轮换,将指令信号的 RISC-V 实现对可选扩 展使用相同的操作码, 扇出和立即数多路复用的成本降低了近两倍,这也简化了低端实现中的数据通路逻辑。 例如 RV32M,RV32F 等。针对特定处理器的 有什么不同之处?在这一章和后面的章节的结束部分,我们将描述 RISC-V 与其他指 非标准扩展只能使用 令集的不同之处。这种对比通常是描述相比于其他指令集,RISC-V 少了什么。省略什么特 RISC-V 中的保留操作 码空间。 性和包括什么特性一样,都能体现架构师的精心设计。 ARM-32 指令集 12 位的立即字段不仅仅是一个常量,而是一个函数的输入,此函数 根据 12 位立即数的输入来产生一个常量:8 位被零扩展到全宽度,然后被循环右移。右移 的位数是 12 位立即数中剩余 4 位的值乘 2。设计者希望在 12 位中编码更多有用的常数来 减少执行指令的数量。在大多数指令格式中,ARM-32 也将十分宝贵的四位编码空间拿出 来专门用于条件执行。这些条件执行指令不仅使用频率低而且增加了乱序处理器的复杂 性。 补充说明:乱序执行处理器 这是一种高速的、流水化的处理器。它们一有机会就执行指令,而不是在按照程序顺序。这 种处理器的一个关键特性是寄存器重命名,把程序中的寄存器名称映射到大量的内部物理 寄存器。条件执行的问题是不管条件是否成立,都必须给这些指令中的寄存器分配相应的物 理寄存器。但内部物理寄存器的可用性是影响乱序处理器的关键性能资源。 2.3 RV32I 寄存器 图 4 列出了 RV32I 寄存器以及由 RISC-V 应用程序二进制接口(ABI)所定义的寄存 器名称。在我们的示例代码中,我们将使用 ABI 名称,使它们更容易阅读。为了满足汇编 语言程序员和编译器编写者,RV32I 有 31 寄存器加上一个值恒为 0 的 x0 寄存器。与之相 比,ARM-32 只有 16 个寄存器,x86-32 甚至只有 8 个寄存器。 有什么不同之处?为常量 0 单独分配一个寄存器是 RISC-V ISA 能如此简单的一个很 大的因素。第 3 章的第 36 页的图 3 给出了许多 ARM-32 和 x86-32 的原生指令操作,这两 个指令集中没有零寄存器。我们可以用 RV32I 指令完成功能相同的操作,只需使用零寄存 器作为操作数。

29. 27 程序计数器(PC)是 ARM-32 的 16 个寄存器之一,这意味着任何改变寄存器的指令 都有可能导致分支跳转。PC 作为一个寄存器使硬件分支预测变得复杂,因为在典型的 ISA 中,仅 10%-20%的指令为分支指令,而在 ARM-32 中,任何指令都有可能是分支指令。而 目前除最便宜的处理 分支预测的准确性对于良好的流水线性能至关重要。另外将 PC 作为一个寄存器也意味着 器以外的所有处理器 都使用流水线来获得 可用的通用寄存器少了一个。 良好的性能。与工业装 配线一样, 它们通过一 次执行多条指令来获 得更高的吞吐量。为了 2.4 RV32I 整数计算 实现这一目标, 处理器 可以预测分支结果, 这 个操作的准确度可以 附录 A 给出了所有 RISC-V 指令的细节信息,包括格式和操作码。在本节以及接下来 超过 90%。若进行了 错误预测, 指令会重新 的章节的类似小节中,我们将给出 ISA 的一些概述。这能够让有基础的汇编语言程序员了 执行。 早期的微处理器 解 RISC-V,同时也顺便说明 RISC-V 的特性如何满足第一章中阐述的七个 ISA 指标。 有一个 5 级流水线,这 意味着 5 条指令并行 简单的算术指令(add, sub)、逻辑指令(and, or, xor),以及图 2.1 中的移位指令 执行。 最近的处理器有 (sll, srl, sra)和其他 ISA 差不多。他们从寄存器读取两个 32 位的值,并将 32 位结果写 10 多个流水级。 入目标寄存器。RV32I 还提供了这些指令的立即数版本。和 ARM-32 不同,立即数总是进 行符号扩展,这样子如果需要,我们可以用立即数表示负数,正因为如此,我们并不需要 一个立即数版本的 sub。 程序可以根据比较结果生成布尔值。为应对这种使用场景下,RV32I 提供一个当小于 时置位的指令。如果第一个操作数小于第二个操作数,它将目标寄存器设置为 1,否则为 0。不出所料,对这个指令,有一个有符号版本(slt)和无符号版本(sltu),分别用于处 理有符号和无符号整数比较。相应的,上述两条指令也有立即数版本的(slti,sltiu)。正 如我们将要看到的,虽然 RV32I 分支指令可以检查两个寄存器之间的所有关系,但一些条 件表达式涉及多对寄存器之间的关系。对于这些表达式,编译器或汇编语言程序员可以将 slt 以及与或异或等逻辑指令组合使用来解决更复杂的条件表达式。 图 2.1 剩下的两条整数计算指令主要用于构造大的常量数值和链接。加载立即数到高 位(lui)将 20 位常量加载到寄存器的高 20 位。接着便可以使用标准的立即指令来创建 32 位常量。这样子,仅使用 2 条 32 位 RV32I 指令,便可构造一个 32 位常量。向 PC 高位加 上立即数(auipc)让我们仅用两条指令,便可以基于当前 PC 以任意偏移量转移控制流或 者访问数据。将 auipc 中的 20 位立即数与 jalr(参见下面)中 12 位立即数的组合,我们 可以将执行流转移到任何 32 位 PC 相对地址。而 auipc 加上普通加载或存储指令中的 12 位立即数偏移量,使我们可以访问任何 32 位 PC 相对地址的数据。 有什么不同之处?首先,RISC-V 中没有字节或半字宽度的整数计算操作。操作始终 是以完整的寄存器宽度。内存访问需要的能量比算术运算高几个数量级。因此低宽度的数 据访问可以节省大量的能量,但低宽度的运算不会。ARM-32 具有一个不寻常的功能,对 于大多数算术逻辑运算中的一个操作数,你可以选择对它进行移位。尽管这些指令的使用 频率很低,但它使数据路径和数据通路更加复杂。与此相对的是,RV32I 提供了单独的移 位指令。 RV32I 也不包含乘法和除法,它们包含在可选的 RV32M 扩展中(参见第 4 章)。与 ARM-32 和 x86-32 不同,即使处理器没有添加乘除法扩展,完整的 RISC-V 软件栈也可以 运行,这可以缩小嵌入式芯片的面积。MIPS-32 汇编程序可能用一系列移位以及加法指令 来替换乘法,以提高性能,这可能会使程序员看到处理器执行了汇编程序中没有的指令, 进而造成混淆。RV32I 可以忽略了这些特性:循环移位指令和整数算术溢出检测,这两个 特性都可以用若干条 RV32I 指令来实现(参见第 2.6 节)。