RISC-V体系结构编程与实践

RISC-V体系结构编程与实践
分享
扫描下方二维码分享到微信
打开微信,点击右上角”+“,
使用”扫一扫“即可将网页分享到朋友圈。
2023-02
版次: 1
ISBN: 9787115603609
定价: 129.80
装帧: 其他
开本: 其他
纸张: 胶版纸
页数: 464页
字数: 745千字
12人买过
  • 本书旨在介绍RISC-V体系结构的设计和实现。本书首先介绍RISC-V体系结构的基础知识、实验环境搭建、常用指令、函数调用规范与栈,然后讲述GNU汇编器、链接器、链接脚本和GCC内嵌汇编代码,接着讨论RISC-V体系结构中的异常处理、中断、内存管理、高速缓存、缓存一致性、TLB管理、原子操作、内存屏障指令,最后阐述RSIC-V体系结构中的压缩指令扩展、虚拟化扩展等。
      本书不仅适合软件开发人员阅读,还可以作为计算机相关专业和相关培训机构的教材。 作者简介 奔跑吧Linux社区 由一群热爱开源的工程师组成,致力于开源硬件和开源软件的推广。 审校者简介 香山处理器团队 面向世界的体系结构创新开源平台,目前已形成由多家企业组成的香山联合开发团队。其中,香山处理器是由中国科学院计算技术研究所发起的开源高性能RISC-V处理器核项目。 龙蜥社区RISC-V SIG 坚持开放、开源,致力于龙蜥社区以及 RISCV 软硬件生态的共建和推广。 进迭时空 专注研发新一代高性能RISC-V处理器和计算系统,让开发者基于RISC-V芯片更自由地开发更有创意的新应用。 目  录

    第 1章 RISC-V体系结构基础知识 1

    1.1 RISC-V介绍 1

    1.1.1 RISC-V指令集优点 1

    1.1.2 RISC-V指令集扩展 2

    1.1.3 RISC-V商业化发展 2

    1.2 RISC-V体系结构介绍 3

    1.2.1 RISC-V体系结构 3

    1.2.2 采用RISC-V体系结构的常见处理器 3

    1.2.3 RISC-V体系结构中的基本概念 4

    1.2.4 SBI服务 5

    1.3 RISC-V寄存器 6

    1.3.1 通用寄存器 6

    1.3.2 系统寄存器 7

    1.3.3 U模式下的系统寄存器 8

    1.3.4 S模式下的系统寄存器 9

    1.3.5 M模式下的系统寄存器 11

    1.4 香山处理器介绍 15

    1.4.1 香山处理器体系结构 15

    1.4.2 香山处理器的前端子系统 16

    1.4.3 香山处理器的后端子系统 18

    1.4.4 香山处理器的访存子系统 20

    1.4.5 香山处理器的L2/L3高速缓存 25

    第 2章 搭建RISC-V实验环境 29

    2.1 实验平台 29

    2.1.1 QEMU 29

    2.1.2 NEMU 30

    2.2 搭建实验环境 31

    2.2.1 实验2-1:输出“Welcome RISC-V!” 31

    2.2.2 实验2-2:单步调试BenOS和MySBI 32

    2.3 BenOS和MySBI基础实验代码解析 34

    2.3.1 MySBI基础代码分析 34

    2.3.2 BenOS基础代码分析 37

    2.3.3 合并BenOS和MySBI 41

    2.4 QEMU   RISC-V   Linux实验平台 41

    第3章 基础指令集 44

    3.1 RISC-V指令集介绍 44

    3.2 RISC-V指令编码格式 45

    3.3 加载与存储指令 46

    3.4 PC相对寻址 49

    3.5 移位操作 53

    3.6 位操作指令 55

    3.7 算术指令 56

    3.8 比较指令 57

    3.9 无条件跳转指令 58

    3.10 条件跳转指令 59

    3.11 CSR指令 61

    3.12 寻址范围 62

    3.13 陷阱:为什么ret之后就进入死循环 62

    3.14 实验 64

    3.14.1 实验3-1:熟悉加载指令 64

    3.14.2 实验3-2:PC相对地址寻址 64

    3.14.3 实验3-3:memcpy()函数的实现 65

    3.14.4 实验3-4:memset()函数的实现 65

    3.14.5 实验3-5:条件跳转指令1 65

    3.14.6 实验3-6:条件跳转指令2 66

    3.14.7 实验3-7:子函数跳转 66

    3.14.8 实验3-8:在汇编中实现串口输出功能 66

    第4章 函数调用规范与栈 67

    4.1 函数调用规范 67

    4.2 入栈与出栈 70

    4.3 RISC-V栈的布局 72

    4.3.1 不使用FP的栈布局 72

    4.3.2 使用FP的栈布局 74

    4.3.3 栈回溯 76

    4.4 实验 78

    4.4.1 实验4-1:观察栈布局 78

    4.4.2 实验4-2:观察栈回溯 78

    第5章 GNU汇编器 79

    5.1 编译流程与ELF文件 79

    5.2 一个简单的汇编程序 82

    5.3 汇编语法 84

    5.3.1 注释 84

    5.3.2 符号 84

    5.4 常用的伪指令 85

    5.4.1 对齐伪指令 85

    5.4.2 数据定义伪指令 86

    5.4.3 与函数相关的伪指令 87

    5.4.4 与段相关的伪指令 87

    5.4.5 与宏相关的伪指令 89

    5.4.6 与文件相关的伪指令 91

    5.5 RISC-V依赖特性 91

    5.5.1 RISC-V特有的命令行选项 91

    5.5.2 RISC-V特有的伪指令 92

    5.6 实验 92

    5.6.1 实验5-1:汇编语言练习—查找最大数 92

    5.6.2 实验5-2:汇编语言练习—通过C语言调用汇编函数 92

    5.6.3 实验5-3:汇编语言练习—通过汇编语言调用C函数 92

    5.6.4 实验5-4:使用汇编伪操作实现一张表 92

    5.6.5 实验5-5:汇编宏的使用 93

    第6章 链接器与链接脚本 94

    6.1 链接器 94

    6.2 链接脚本 95

    6.2.1 一个简单的链接程序 95

    6.2.2 设置入口点 96

    6.2.3 基本概念 97

    6.2.4 符号赋值与引用 97

    6.2.5 当前位置计数器 98

    6.2.6 SECTIONS命令 99

    6.2.7 常用的内置函数 101

    6.3 加载重定位 103

    6.3.1 BenOS重定位 103

    6.3.2 OpenSBI和Linux内核重定位 105

    6.4 链接重定位与链接器松弛优化 108

    6.4.1 链接重定位 108

    6.4.2 函数跳转优化 112

    6.4.3 符号地址访问优化 114

    6.5 实验 116

    6.5.1 实验6-1:分析链接脚本 116

    6.5.2 实验6-2:输出每个段的内存布局 116

    6.5.3 实验6-3:加载地址不等于运行地址 117

    6.5.4 实验6-4:设置链接地址 117

    6.5.5 实验6-5:链接器松弛优化1 117

    6.5.6 实验6-6:链接器松弛优化2 117

    6.5.7 实验6-7:分析Linux 5.15内核的链接脚本 117

    第7章 内嵌汇编代码 118

    7.1 内嵌汇编代码基本用法 118

    7.1.1 基础内嵌汇编代码 118

    7.1.2 扩展内嵌汇编代码 118

    7.1.3 内嵌汇编代码修饰符 120

    7.1.4 使用汇编符号名字 121

    7.1.5 内嵌汇编代码与宏结合 122

    7.1.6 使用goto修饰词 122

    7.1.7 小结 123

    7.2 案例分析 124

    7.3 注意事项 128

    7.4 实验 128

    7.4.1 实验7-1:实现简单的memcpy()函数 128

    7.4.2 实验7-2:使用汇编符号名写内嵌汇编代码 128

    7.4.3 实验7-3:使用内嵌汇编代码完善memset()函数 129

    7.4.4 实验7-4:使用内嵌汇编代码与宏的结合 129

    7.4.5 实验7-5:实现读和写系统寄存器的宏 129

    7.4.6 实验7-6:goto模板的内嵌汇编代码 129

    第8章 异常处理 130

    8.1 异常处理基本概念 130

    8.1.1 异常类型 130

    8.1.2 同步异常和异步异常 131

    8.1.3 异常入口和返回 131

    8.1.4 异常返回地址 132

    8.1.5 异常返回的处理器模式 133

    8.1.6 栈的选择 133

    8.2 与M模式相关的异常寄存器 133

    8.2.1 mstatus寄存器 134

    8.2.2 mtvec寄存器 134

    8.2.3 mcause寄存器 135

    8.2.4 mie寄存器 135

    8.2.5 mtval寄存器 136

    8.2.6 mip寄存器 136

    8.2.7 mideleg和medeleg寄存器 136

    8.2.8 中断配置 137

    8.3 与S模式相关的异常寄存器 137

    8.3.1 sstatus寄存器 137

    8.3.2 sie寄存器 137

    8.3.3 sip寄存器 138

    8.3.4 scause寄存器 138

    8.3.5 stvec寄存器 138

    8.3.6 stval寄存器 139

    8.4 异常上下文 139

    8.4.1 保存异常上下文 141

    8.4.2 恢复异常上下文 141

    8.5 案例分析8-1:实现SBI系统调用 142

    8.5.1 调用ECALL指令 142

    8.5.2 实现SBI系统调用 143

    8.6 案例分析8-2:BenOS的异常处理 148

    8.6.1 设置异常向量表 148

    8.6.2 保存和恢复异常上下文 149

    8.6.3 异常处理 151

    8.6.4 委托中断和异常 153

    8.6.5 触发异常 153

    8.7 实验 154

    8.7.1 实验8-1:在SBI中实现串口输入功能 154

    8.7.2 实验8-2:在BenOS中触发非法指令异常 155

    8.7.3 实验8-3:输出触发异常时函数栈的调用过程 155

    8.7.4 实验8-4:在MySBI中模拟实现RDTIME伪指令 155

    第9章 中断处理与中断控制器 156

    9.1 中断处理基本概念 156

    9.1.1 中断类型 156

    9.1.2 中断处理过程 157

    9.1.3 中断委派和注入 158

    9.1.4 中断优先级 158

    9.2 CLINT 159

    9.3 案例分析9-1:定时器中断 160

    9.3.1 访问mtimer 160

    9.3.2 在MySBI中实现定时器服务 160

    9.3.3 定时器中断处理 161

    9.3.4 打开中断总开关 163

    9.3.5 小结 164

    9.4 PLIC 164

    9.4.1 中断号 165

    9.4.2 中断优先级 166

    9.4.3 中断使能寄存器 166

    9.4.4 中断待定寄存器 166

    9.4.5 中断优先级阈值寄存器 167

    9.4.6 中断请求/完成寄存器 167

    9.5 案例分析9-2:串口中断 167

    9.5.1 初始化PLIC 168

    9.5.2 使能串口0的接收中断 169

    9.5.3 处理中断 169

    9.6 实验 171

    9.6.1 实验9-1:定时器中断 171

    9.6.2 实验9-2:使用汇编函数保存和恢复中断现场 171

    9.6.3 实验9-3:实现并调试串口0中断 171

    第 10章 内存管理 172

    10.1 内存管理基础知识 172

    10.1.1 内存管理的“远古时代” 172

    10.1.2 地址空间的抽象 174

    10.1.3 分段机制 175

    10.1.4 分页机制 175

    10.2 RISC-V内存管理 178

    10.2.1 页表分类 179

    10.2.2 Sv39页表映射 180

    10.2.3 Sv48页表映射 182

    10.2.4 页表项描述符 183

    10.2.5 页表属性 185

    10.2.6 与地址转换相关的寄存器 186

    10.3 物理内存属性与物理内存保护 187

    10.3.1 物理内存属性 187

    10.3.2 物理内存保护 188

    10.4 案例分析10-1:在BenOS里实现恒等映射 190

    10.4.1 页表定义 191

    10.4.2 页表数据结构 193

    10.4.3 创建页表 193

    10.4.4 打开MMU 198

    10.4.5 测试MMU 198

    10.4.6 图解页表创建的过程 200

    10.5 内存管理实验 204

    10.5.1 实验10-1:建立恒等映射 204

    10.5.2 实验10-2:为什么MMU无法运行 205

    10.5.3 实验10-3:实现一个MMU页表的转储功能 205

    10.5.4 实验10-4:修改页面属性 205

    10.5.5 实验10-5:使用汇编语言来建立恒等映射 206

    10.5.6 实验10-6:在MySBI中实现和验证PMP机制 206

    第 11章 高速缓存 207

    11.1 为什么需要高速缓存 207

    11.2 高速缓存的访问延时 208

    11.3 高速缓存的工作原理 210

    11.4 高速缓存的映射方式 212

    11.4.1 直接映射 212

    11.4.2 全相联映射 213

    11.4.3 组相联映射 213

    11.4.4 组相联的高速缓存的例子 214

    11.5 虚拟高速缓存与物理高速缓存 215

    11.5.1 物理高速缓存 215

    11.5.2 虚拟高速缓存 215

    11.5.3 VIPT和PIPT 215

    11.6 重名和同名问题 216

    11.6.1 重名问题 217

    11.6.2 同名问题 217

    11.6.3 VIPT产生的重名问题 218

    11.7 高速缓存策略 220

    11.8 高速缓存的维护指令 221

    11.8.1 高速缓存管理指令 221

    11.8.2 高速缓存预取指令 222

    第 12章 缓存一致性 224

    12.1 为什么需要缓存一致性 224

    12.2 缓存一致性的分类 225

    12.2.1 缓存一致性协议发展历程 225

    12.2.2 缓存一致性分类 226

    12.2.3 系统缓存一致性问题 227

    12.3 缓存一致性的解决方案 227

    12.3.1 关闭高速缓存 228

    12.3.2 使用软件维护缓存一致性 228

    12.3.3 使用硬件维护缓存一致性 228

    12.4 MESI协议 228

    12.4.1 MESI协议简介 229

    12.4.2 本地读写与总线操作 230

    12.4.3 MESI状态转换 230

    12.4.4 初始状态为I 231

    12.4.5 初始状态为M 233

    12.4.6 初始状态为S 234

    12.4.7 初始状态为E 234

    12.4.8 小结与案例分析 235

    12.4.9 MOESI协议 237

    12.5 高速缓存伪共享 237

    12.6 两种缓存一致性控制器 239

    12.6.1 CCI缓存一致性控制器 239

    12.6.2 CCN缓存一致性控制器 240

    12.7 案例分析12-1:伪共享的避免 241

    12.8 案例分析12-2:DMA和高速缓存的一致性 242

    12.8.1 从内存到设备的FIFO缓冲区 243

    12.8.2 从设备的FIFO缓冲区到内存 243

    12.9 案例分析12-3:自修改代码的一致性 244

    12.10 实验 245

    12.10.1 实验12-1:高速缓存伪共享 245

    12.10.2 实验12-2:使用Perf C2C发现高速缓存伪共享 245

    第 13章 TLB管理 246

    13.1 TLB基础知识 247

    13.2 TLB重名与同名问题 249

    13.2.1 重名问题 249

    13.2.2 同名问题 250

    13.3 ASID 251

    13.4 TLB管理指令 253

    13.4.1 TLB维护指令介绍 253

    13.4.2 TLB广播 254

    13.4.3 SFENCE.VMA指令使用场景 256

    13.5 TLB案例分析 256

    13.5.1 TLB在Linux内核中的应用 256

    13.5.2 ASID在Linux内核中的应用 257

    13.5.3 Linux内核中的TLB维护操作 257

    13.5.4 BBM机制 259

    第 14章 原子操作 261

    14.1 原子操作介绍 261

    14.2 保留加载与条件存储指令 262

    14.3 独占内存访问工作原理 263

    14.3.1 独占监视器 264

    14.3.2 独占监视器与缓存一致性 265

    14.4 原子内存访问操作指令 266

    14.4.1 原子内存访问指令工作原理 266

    14.4.2 原子内存访问指令与LR/SC指令的效率对比 267

    14.4.3 RISC-V中的原子内存访问指令 268

    14.5 比较并交换操作 270

    第 15章 内存屏障指令 275

    15.1 内存屏障指令产生的原因 275

    15.1.1 顺序一致性内存模型 276

    15.1.2 处理器一致性内存模型 277

    15.1.3 弱一致性内存模型 277

    15.1.4 释放一致性内存模型 278

    15.1.5 MCA模型 279

    15.2 RISC-V约束条件 280

    15.2.1 全局内存次序与保留程序次序 280

    15.2.2 RVWMO的约束规则 281

    15.3 RISC-V中的内存屏障指令 284

    15.3.1 使用内存屏障的场景 284

    15.3.2 FENCE指令 285

    15.3.3 内置获取和释放屏障原语的指令 285

    15.3.4 FENCE.I指令 286

    15.3.5 SFENCE.VMA指令 286

    15.4 RISC-V内存屏障指令移植指南 286

    15.4.1 从RISC-V到x86体系结构 286

    15.4.2 从RISC-V到ARM体系结构 287

    15.4.3 Linux内核常用的内存屏障API函数 287

    15.5 案例分析 288

    15.5.1 消息传递问题 288

    15.5.2 单方向内存屏障与自旋锁 289

    15.5.3 邮箱传递消息 290

    15.5.4 关于DMA的案例 291

    15.5.5 在Linux内核中使指令高速缓存失效 291

    15.6 模拟和测试内存屏障故障 291

    15.6.1 使用Litmus测试工具集 292

    15.6.2 编写C程序来模拟 295

    15.7 实验 297

    15.7.1 实验15-1:编写Litmus脚本并测试内存一致性1 297

    15.7.2 实验15-2:编写Litmus脚本并测试内存一致性2 298

    第 16章 合理使用内存屏障指令 299

    16.1 存储缓冲区与写内存屏障指令 300

    16.2 无效队列与读内存屏障指令 305

    16.3 内存屏障指令总结 307

    16.4 案例分析:Linux内核中的内存屏障指令 308

    16.4.1 第 一次使用内存屏障指令 309

    16.4.2 第二次使用内存屏障指令 310

    16.4.3 第三次使用内存屏障指令 313

    16.4.4 第四次使用内存屏障指令 314

    16.4.5 小结:内存屏障指令的使用 315

    16.5 实验 315

    16.5.1 实验16-1:验证和测试内存一致性1 315

    16.5.2 实验16-2:验证和测试内存一致性2 315

    16.5.3 实验16-3:验证和测试内存一致性3 315

    第 17章 与操作系统相关的内容 316

    17.1 C语言常见陷阱 317

    17.1.1 数据模型 317

    17.1.2 数据类型转换与整型提升 318

    17.1.3 移位操作 320

    17.2 创建进程 320

    17.2.1 进程控制块 320

    17.2.2 0号进程 321

    17.2.3 do_fork()函数的实现 323

    17.2.4 进程上下文切换 324

    17.2.5 新进程的第 一次执行 326

    17.3 简易进程调度器 327

    17.3.1 扩展进程控制块 327

    17.3.2 就绪队列 327

    17.3.3 调度类 328

    17.3.4 简易调度器的实现 329

    17.3.5 自愿调度 330

    17.3.6 抢占调度 331

    17.3.7 测试用例 333

    17.3.8 关于调度的思考 333

    17.4 让进程运行在用户模式 335

    17.5 系统调用 338

    17.5.1 系统调用介绍 338

    17.5.2 在用户模式下调用SVC指令 338

    17.5.3 在内核模式下对系统调用的处理 339

    17.5.4 系统调用表 340

    17.6 实现clone系统调用 341

    17.7 实验 343

    17.7.1 实验17-1:进程创建 343

    17.7.2 实验17-2:进程调度 343

    17.7.3 实验17-3:让进程运行在用户模式 343

    17.7.4 实验17-4:新增一个malloc()系统调用 343

    17.7.5 实验17-5:新增一个clone()系统调用 344

    第 18章 可伸缩矢量计算与优化 345

    18.1 矢量计算基本概念 345

    18.1.1 SISD与SIMD 345

    18.1.2 定长计算与可变长矢量计算 347

    18.1.3 通道 347

    18.1.4 矢量与标量 347

    18.2 RVV寄存器 348

    18.2.1 矢量寄存器 348

    18.2.2 mstatus寄存器中的矢量上下文状态 348

    18.2.3 vtype寄存器 348

    18.2.4 vl寄存器 350

    18.2.5 vlenb寄存器 351

    18.2.6 vstart寄存器 351

    18.3 配置编译和运行环境 351

    18.3.1 搭建编译环境 351

    18.3.2 运行第 一个“hello RVV!”程序 352

    18.3.3 单步调试汇编程序 353

    18.3.4 单步调试C语言与汇编混合程序 355

    18.4 RVV指令格式 357

    18.5 配置指令 358

    18.6 加载和存储指令 360

    18.6.1 单位步长模式 360

    18.6.2 任意步长模式 363

    18.6.3 聚合加载/离散存储 364

    18.6.4 打包数据的加载与存储 365

    18.6.5 首次异常加载指令 367

    18.6.6 加载和存储全部矢量数据 368

    18.7 矢量掩码指令 369

    18.7.1 逻辑操作指令 369

    18.7.2 VCPOP.M指令 369

    18.7.3 VFIRST.M指令 370

    18.7.4 VMSBF.M指令 370

    18.7.5 VMSIF.M指令 371

    18.7.6 VMSOF.M指令 372

    18.8 矢量整型算术指令 372

    18.8.1 加宽和变窄算术指令 372

    18.8.2 加法和减法指令 373

    18.8.3 加宽模式的加法和减法指令 374

    18.8.4 位操作指令 376

    18.8.5 移位操作指令 376

    18.8.6 比较指令 376

    18.8.7 数据搬移指令 377

    18.9 案例分析18-1:使用RVV指令优化strcmp()函数 377

    18.9.1 使用纯汇编方式 378

    18.9.2 测试 379

    18.10 案例分析18-2:RGB24转BGR24 380

    18.10.1 使用C语言实现RGB24转BGR24 380

    18.10.2 使用RVV指令优化 380

    18.10.3 测试 381

    18.11 案例分析18-3:4 × 4矩阵乘法运算 382

    18.11.1 使用C语言实现4 × 4矩阵乘法运算 382

    18.11.2 使用RVV指令优化 383

    18.11.3 测试 387

    18.12 案例分析18-4:使用RVV内置函数 388

    18.13 案例分析18-5:自动矢量优化 388

    18.14 术语 390

    18.15 实验 391

    18.15.1 实验18-1:RGB24转BGR32 391

    18.15.2 实验18-2:8 × 8矩阵乘法运算 391

    18.15.3 实验18-3:使用RVV指令优化strcpy()函数 391

    18.15.4 实验18-4:使用RVV内置函数优化 391

    18.15.5 实验18-5:使用RVV优化转置矩阵的求法 392

    第 19章 压缩指令扩展 393

    19.1 RISC-V指令集的特点 393

    19.2 RVC支持的指令格式与指令编码 394

    第 20章 虚拟化扩展 396

    20.1 虚拟化技术介绍 396

    20.1.1 虚拟化技术的发展历史 396

    20.1.2 虚拟机管理程序的分类 398

    20.1.3 内存虚拟化 398

    20.1.4 I/O虚拟化 399

    20.2 RISC-V虚拟化扩展 399

    20.2.1 CPU虚拟化扩展 399

    20.2.2 M模式下系统寄存器的扩展 400

    20.2.3 HS模式下的系统寄存器 402

    20.2.4 VS模式下的系统寄存器 404

    20.3 RISC-V内存虚拟化 404

    20.4 RISC-V虚拟化扩展中的新增指令 406

    20.4.1 加载与存储虚拟机内存指令 406

    20.4.2 虚拟化内存屏障指令 406

    20.5 进入和退出虚拟机 407

    20.5.1 异常陷入 408

    20.5.2 异常返回 408

    20.5.3 新增的中断与异常类型 409

    20.6 中断虚拟化 410

    20.6.1 虚拟中断注入 410

    20.6.2 陷入与模拟 411

    20.7 案例分析20-1:进入和退出虚拟机 412

    20.7.1 进入虚拟机 413

    20.7.2 退出虚拟机 414

    20.8 案例分析20-2:建立虚拟化两阶段地址映射 415

    20.8.1 建立第二阶段的地址映射 416

    20.8.2 建立第 一阶段的地址映射 418

    20.8.3 测试 419

    20.9 案例分析20-3:在虚拟机中实现虚拟定时器 420

    20.10 案例分析20-4:在VMM中加载和存储虚拟机内存地址 422

    20.11 案例分析20-5:在VMM中模拟串口设备 424

    20.12 实验 429

    20.12.1 实验20-1:加载虚拟机1 429

    20.12.2 实验20-2:加载虚拟机2 430

    20.12.3 实验20-3:虚拟化地址映射 430

    20.12.4 实验20-4:解析虚拟机陷入的指令 430

    20.12.5 实验20-5:在VMM中模拟实现vPLIC 430

    20.12.6 实验20-6:在虚拟机中加载并运行Linux内核 430

    附录A 关于RISC-V体系结构自测题的参考答案与提示 431

    附录B RV64I指令速查表 433

    附录C RV64M指令速查表 437

    附录D RV64常用伪指令速查表 439
  • 内容简介:
    本书旨在介绍RISC-V体系结构的设计和实现。本书首先介绍RISC-V体系结构的基础知识、实验环境搭建、常用指令、函数调用规范与栈,然后讲述GNU汇编器、链接器、链接脚本和GCC内嵌汇编代码,接着讨论RISC-V体系结构中的异常处理、中断、内存管理、高速缓存、缓存一致性、TLB管理、原子操作、内存屏障指令,最后阐述RSIC-V体系结构中的压缩指令扩展、虚拟化扩展等。
      本书不仅适合软件开发人员阅读,还可以作为计算机相关专业和相关培训机构的教材。
  • 作者简介:
    作者简介 奔跑吧Linux社区 由一群热爱开源的工程师组成,致力于开源硬件和开源软件的推广。 审校者简介 香山处理器团队 面向世界的体系结构创新开源平台,目前已形成由多家企业组成的香山联合开发团队。其中,香山处理器是由中国科学院计算技术研究所发起的开源高性能RISC-V处理器核项目。 龙蜥社区RISC-V SIG 坚持开放、开源,致力于龙蜥社区以及 RISCV 软硬件生态的共建和推广。 进迭时空 专注研发新一代高性能RISC-V处理器和计算系统,让开发者基于RISC-V芯片更自由地开发更有创意的新应用。
  • 目录:
    目  录

    第 1章 RISC-V体系结构基础知识 1

    1.1 RISC-V介绍 1

    1.1.1 RISC-V指令集优点 1

    1.1.2 RISC-V指令集扩展 2

    1.1.3 RISC-V商业化发展 2

    1.2 RISC-V体系结构介绍 3

    1.2.1 RISC-V体系结构 3

    1.2.2 采用RISC-V体系结构的常见处理器 3

    1.2.3 RISC-V体系结构中的基本概念 4

    1.2.4 SBI服务 5

    1.3 RISC-V寄存器 6

    1.3.1 通用寄存器 6

    1.3.2 系统寄存器 7

    1.3.3 U模式下的系统寄存器 8

    1.3.4 S模式下的系统寄存器 9

    1.3.5 M模式下的系统寄存器 11

    1.4 香山处理器介绍 15

    1.4.1 香山处理器体系结构 15

    1.4.2 香山处理器的前端子系统 16

    1.4.3 香山处理器的后端子系统 18

    1.4.4 香山处理器的访存子系统 20

    1.4.5 香山处理器的L2/L3高速缓存 25

    第 2章 搭建RISC-V实验环境 29

    2.1 实验平台 29

    2.1.1 QEMU 29

    2.1.2 NEMU 30

    2.2 搭建实验环境 31

    2.2.1 实验2-1:输出“Welcome RISC-V!” 31

    2.2.2 实验2-2:单步调试BenOS和MySBI 32

    2.3 BenOS和MySBI基础实验代码解析 34

    2.3.1 MySBI基础代码分析 34

    2.3.2 BenOS基础代码分析 37

    2.3.3 合并BenOS和MySBI 41

    2.4 QEMU   RISC-V   Linux实验平台 41

    第3章 基础指令集 44

    3.1 RISC-V指令集介绍 44

    3.2 RISC-V指令编码格式 45

    3.3 加载与存储指令 46

    3.4 PC相对寻址 49

    3.5 移位操作 53

    3.6 位操作指令 55

    3.7 算术指令 56

    3.8 比较指令 57

    3.9 无条件跳转指令 58

    3.10 条件跳转指令 59

    3.11 CSR指令 61

    3.12 寻址范围 62

    3.13 陷阱:为什么ret之后就进入死循环 62

    3.14 实验 64

    3.14.1 实验3-1:熟悉加载指令 64

    3.14.2 实验3-2:PC相对地址寻址 64

    3.14.3 实验3-3:memcpy()函数的实现 65

    3.14.4 实验3-4:memset()函数的实现 65

    3.14.5 实验3-5:条件跳转指令1 65

    3.14.6 实验3-6:条件跳转指令2 66

    3.14.7 实验3-7:子函数跳转 66

    3.14.8 实验3-8:在汇编中实现串口输出功能 66

    第4章 函数调用规范与栈 67

    4.1 函数调用规范 67

    4.2 入栈与出栈 70

    4.3 RISC-V栈的布局 72

    4.3.1 不使用FP的栈布局 72

    4.3.2 使用FP的栈布局 74

    4.3.3 栈回溯 76

    4.4 实验 78

    4.4.1 实验4-1:观察栈布局 78

    4.4.2 实验4-2:观察栈回溯 78

    第5章 GNU汇编器 79

    5.1 编译流程与ELF文件 79

    5.2 一个简单的汇编程序 82

    5.3 汇编语法 84

    5.3.1 注释 84

    5.3.2 符号 84

    5.4 常用的伪指令 85

    5.4.1 对齐伪指令 85

    5.4.2 数据定义伪指令 86

    5.4.3 与函数相关的伪指令 87

    5.4.4 与段相关的伪指令 87

    5.4.5 与宏相关的伪指令 89

    5.4.6 与文件相关的伪指令 91

    5.5 RISC-V依赖特性 91

    5.5.1 RISC-V特有的命令行选项 91

    5.5.2 RISC-V特有的伪指令 92

    5.6 实验 92

    5.6.1 实验5-1:汇编语言练习—查找最大数 92

    5.6.2 实验5-2:汇编语言练习—通过C语言调用汇编函数 92

    5.6.3 实验5-3:汇编语言练习—通过汇编语言调用C函数 92

    5.6.4 实验5-4:使用汇编伪操作实现一张表 92

    5.6.5 实验5-5:汇编宏的使用 93

    第6章 链接器与链接脚本 94

    6.1 链接器 94

    6.2 链接脚本 95

    6.2.1 一个简单的链接程序 95

    6.2.2 设置入口点 96

    6.2.3 基本概念 97

    6.2.4 符号赋值与引用 97

    6.2.5 当前位置计数器 98

    6.2.6 SECTIONS命令 99

    6.2.7 常用的内置函数 101

    6.3 加载重定位 103

    6.3.1 BenOS重定位 103

    6.3.2 OpenSBI和Linux内核重定位 105

    6.4 链接重定位与链接器松弛优化 108

    6.4.1 链接重定位 108

    6.4.2 函数跳转优化 112

    6.4.3 符号地址访问优化 114

    6.5 实验 116

    6.5.1 实验6-1:分析链接脚本 116

    6.5.2 实验6-2:输出每个段的内存布局 116

    6.5.3 实验6-3:加载地址不等于运行地址 117

    6.5.4 实验6-4:设置链接地址 117

    6.5.5 实验6-5:链接器松弛优化1 117

    6.5.6 实验6-6:链接器松弛优化2 117

    6.5.7 实验6-7:分析Linux 5.15内核的链接脚本 117

    第7章 内嵌汇编代码 118

    7.1 内嵌汇编代码基本用法 118

    7.1.1 基础内嵌汇编代码 118

    7.1.2 扩展内嵌汇编代码 118

    7.1.3 内嵌汇编代码修饰符 120

    7.1.4 使用汇编符号名字 121

    7.1.5 内嵌汇编代码与宏结合 122

    7.1.6 使用goto修饰词 122

    7.1.7 小结 123

    7.2 案例分析 124

    7.3 注意事项 128

    7.4 实验 128

    7.4.1 实验7-1:实现简单的memcpy()函数 128

    7.4.2 实验7-2:使用汇编符号名写内嵌汇编代码 128

    7.4.3 实验7-3:使用内嵌汇编代码完善memset()函数 129

    7.4.4 实验7-4:使用内嵌汇编代码与宏的结合 129

    7.4.5 实验7-5:实现读和写系统寄存器的宏 129

    7.4.6 实验7-6:goto模板的内嵌汇编代码 129

    第8章 异常处理 130

    8.1 异常处理基本概念 130

    8.1.1 异常类型 130

    8.1.2 同步异常和异步异常 131

    8.1.3 异常入口和返回 131

    8.1.4 异常返回地址 132

    8.1.5 异常返回的处理器模式 133

    8.1.6 栈的选择 133

    8.2 与M模式相关的异常寄存器 133

    8.2.1 mstatus寄存器 134

    8.2.2 mtvec寄存器 134

    8.2.3 mcause寄存器 135

    8.2.4 mie寄存器 135

    8.2.5 mtval寄存器 136

    8.2.6 mip寄存器 136

    8.2.7 mideleg和medeleg寄存器 136

    8.2.8 中断配置 137

    8.3 与S模式相关的异常寄存器 137

    8.3.1 sstatus寄存器 137

    8.3.2 sie寄存器 137

    8.3.3 sip寄存器 138

    8.3.4 scause寄存器 138

    8.3.5 stvec寄存器 138

    8.3.6 stval寄存器 139

    8.4 异常上下文 139

    8.4.1 保存异常上下文 141

    8.4.2 恢复异常上下文 141

    8.5 案例分析8-1:实现SBI系统调用 142

    8.5.1 调用ECALL指令 142

    8.5.2 实现SBI系统调用 143

    8.6 案例分析8-2:BenOS的异常处理 148

    8.6.1 设置异常向量表 148

    8.6.2 保存和恢复异常上下文 149

    8.6.3 异常处理 151

    8.6.4 委托中断和异常 153

    8.6.5 触发异常 153

    8.7 实验 154

    8.7.1 实验8-1:在SBI中实现串口输入功能 154

    8.7.2 实验8-2:在BenOS中触发非法指令异常 155

    8.7.3 实验8-3:输出触发异常时函数栈的调用过程 155

    8.7.4 实验8-4:在MySBI中模拟实现RDTIME伪指令 155

    第9章 中断处理与中断控制器 156

    9.1 中断处理基本概念 156

    9.1.1 中断类型 156

    9.1.2 中断处理过程 157

    9.1.3 中断委派和注入 158

    9.1.4 中断优先级 158

    9.2 CLINT 159

    9.3 案例分析9-1:定时器中断 160

    9.3.1 访问mtimer 160

    9.3.2 在MySBI中实现定时器服务 160

    9.3.3 定时器中断处理 161

    9.3.4 打开中断总开关 163

    9.3.5 小结 164

    9.4 PLIC 164

    9.4.1 中断号 165

    9.4.2 中断优先级 166

    9.4.3 中断使能寄存器 166

    9.4.4 中断待定寄存器 166

    9.4.5 中断优先级阈值寄存器 167

    9.4.6 中断请求/完成寄存器 167

    9.5 案例分析9-2:串口中断 167

    9.5.1 初始化PLIC 168

    9.5.2 使能串口0的接收中断 169

    9.5.3 处理中断 169

    9.6 实验 171

    9.6.1 实验9-1:定时器中断 171

    9.6.2 实验9-2:使用汇编函数保存和恢复中断现场 171

    9.6.3 实验9-3:实现并调试串口0中断 171

    第 10章 内存管理 172

    10.1 内存管理基础知识 172

    10.1.1 内存管理的“远古时代” 172

    10.1.2 地址空间的抽象 174

    10.1.3 分段机制 175

    10.1.4 分页机制 175

    10.2 RISC-V内存管理 178

    10.2.1 页表分类 179

    10.2.2 Sv39页表映射 180

    10.2.3 Sv48页表映射 182

    10.2.4 页表项描述符 183

    10.2.5 页表属性 185

    10.2.6 与地址转换相关的寄存器 186

    10.3 物理内存属性与物理内存保护 187

    10.3.1 物理内存属性 187

    10.3.2 物理内存保护 188

    10.4 案例分析10-1:在BenOS里实现恒等映射 190

    10.4.1 页表定义 191

    10.4.2 页表数据结构 193

    10.4.3 创建页表 193

    10.4.4 打开MMU 198

    10.4.5 测试MMU 198

    10.4.6 图解页表创建的过程 200

    10.5 内存管理实验 204

    10.5.1 实验10-1:建立恒等映射 204

    10.5.2 实验10-2:为什么MMU无法运行 205

    10.5.3 实验10-3:实现一个MMU页表的转储功能 205

    10.5.4 实验10-4:修改页面属性 205

    10.5.5 实验10-5:使用汇编语言来建立恒等映射 206

    10.5.6 实验10-6:在MySBI中实现和验证PMP机制 206

    第 11章 高速缓存 207

    11.1 为什么需要高速缓存 207

    11.2 高速缓存的访问延时 208

    11.3 高速缓存的工作原理 210

    11.4 高速缓存的映射方式 212

    11.4.1 直接映射 212

    11.4.2 全相联映射 213

    11.4.3 组相联映射 213

    11.4.4 组相联的高速缓存的例子 214

    11.5 虚拟高速缓存与物理高速缓存 215

    11.5.1 物理高速缓存 215

    11.5.2 虚拟高速缓存 215

    11.5.3 VIPT和PIPT 215

    11.6 重名和同名问题 216

    11.6.1 重名问题 217

    11.6.2 同名问题 217

    11.6.3 VIPT产生的重名问题 218

    11.7 高速缓存策略 220

    11.8 高速缓存的维护指令 221

    11.8.1 高速缓存管理指令 221

    11.8.2 高速缓存预取指令 222

    第 12章 缓存一致性 224

    12.1 为什么需要缓存一致性 224

    12.2 缓存一致性的分类 225

    12.2.1 缓存一致性协议发展历程 225

    12.2.2 缓存一致性分类 226

    12.2.3 系统缓存一致性问题 227

    12.3 缓存一致性的解决方案 227

    12.3.1 关闭高速缓存 228

    12.3.2 使用软件维护缓存一致性 228

    12.3.3 使用硬件维护缓存一致性 228

    12.4 MESI协议 228

    12.4.1 MESI协议简介 229

    12.4.2 本地读写与总线操作 230

    12.4.3 MESI状态转换 230

    12.4.4 初始状态为I 231

    12.4.5 初始状态为M 233

    12.4.6 初始状态为S 234

    12.4.7 初始状态为E 234

    12.4.8 小结与案例分析 235

    12.4.9 MOESI协议 237

    12.5 高速缓存伪共享 237

    12.6 两种缓存一致性控制器 239

    12.6.1 CCI缓存一致性控制器 239

    12.6.2 CCN缓存一致性控制器 240

    12.7 案例分析12-1:伪共享的避免 241

    12.8 案例分析12-2:DMA和高速缓存的一致性 242

    12.8.1 从内存到设备的FIFO缓冲区 243

    12.8.2 从设备的FIFO缓冲区到内存 243

    12.9 案例分析12-3:自修改代码的一致性 244

    12.10 实验 245

    12.10.1 实验12-1:高速缓存伪共享 245

    12.10.2 实验12-2:使用Perf C2C发现高速缓存伪共享 245

    第 13章 TLB管理 246

    13.1 TLB基础知识 247

    13.2 TLB重名与同名问题 249

    13.2.1 重名问题 249

    13.2.2 同名问题 250

    13.3 ASID 251

    13.4 TLB管理指令 253

    13.4.1 TLB维护指令介绍 253

    13.4.2 TLB广播 254

    13.4.3 SFENCE.VMA指令使用场景 256

    13.5 TLB案例分析 256

    13.5.1 TLB在Linux内核中的应用 256

    13.5.2 ASID在Linux内核中的应用 257

    13.5.3 Linux内核中的TLB维护操作 257

    13.5.4 BBM机制 259

    第 14章 原子操作 261

    14.1 原子操作介绍 261

    14.2 保留加载与条件存储指令 262

    14.3 独占内存访问工作原理 263

    14.3.1 独占监视器 264

    14.3.2 独占监视器与缓存一致性 265

    14.4 原子内存访问操作指令 266

    14.4.1 原子内存访问指令工作原理 266

    14.4.2 原子内存访问指令与LR/SC指令的效率对比 267

    14.4.3 RISC-V中的原子内存访问指令 268

    14.5 比较并交换操作 270

    第 15章 内存屏障指令 275

    15.1 内存屏障指令产生的原因 275

    15.1.1 顺序一致性内存模型 276

    15.1.2 处理器一致性内存模型 277

    15.1.3 弱一致性内存模型 277

    15.1.4 释放一致性内存模型 278

    15.1.5 MCA模型 279

    15.2 RISC-V约束条件 280

    15.2.1 全局内存次序与保留程序次序 280

    15.2.2 RVWMO的约束规则 281

    15.3 RISC-V中的内存屏障指令 284

    15.3.1 使用内存屏障的场景 284

    15.3.2 FENCE指令 285

    15.3.3 内置获取和释放屏障原语的指令 285

    15.3.4 FENCE.I指令 286

    15.3.5 SFENCE.VMA指令 286

    15.4 RISC-V内存屏障指令移植指南 286

    15.4.1 从RISC-V到x86体系结构 286

    15.4.2 从RISC-V到ARM体系结构 287

    15.4.3 Linux内核常用的内存屏障API函数 287

    15.5 案例分析 288

    15.5.1 消息传递问题 288

    15.5.2 单方向内存屏障与自旋锁 289

    15.5.3 邮箱传递消息 290

    15.5.4 关于DMA的案例 291

    15.5.5 在Linux内核中使指令高速缓存失效 291

    15.6 模拟和测试内存屏障故障 291

    15.6.1 使用Litmus测试工具集 292

    15.6.2 编写C程序来模拟 295

    15.7 实验 297

    15.7.1 实验15-1:编写Litmus脚本并测试内存一致性1 297

    15.7.2 实验15-2:编写Litmus脚本并测试内存一致性2 298

    第 16章 合理使用内存屏障指令 299

    16.1 存储缓冲区与写内存屏障指令 300

    16.2 无效队列与读内存屏障指令 305

    16.3 内存屏障指令总结 307

    16.4 案例分析:Linux内核中的内存屏障指令 308

    16.4.1 第 一次使用内存屏障指令 309

    16.4.2 第二次使用内存屏障指令 310

    16.4.3 第三次使用内存屏障指令 313

    16.4.4 第四次使用内存屏障指令 314

    16.4.5 小结:内存屏障指令的使用 315

    16.5 实验 315

    16.5.1 实验16-1:验证和测试内存一致性1 315

    16.5.2 实验16-2:验证和测试内存一致性2 315

    16.5.3 实验16-3:验证和测试内存一致性3 315

    第 17章 与操作系统相关的内容 316

    17.1 C语言常见陷阱 317

    17.1.1 数据模型 317

    17.1.2 数据类型转换与整型提升 318

    17.1.3 移位操作 320

    17.2 创建进程 320

    17.2.1 进程控制块 320

    17.2.2 0号进程 321

    17.2.3 do_fork()函数的实现 323

    17.2.4 进程上下文切换 324

    17.2.5 新进程的第 一次执行 326

    17.3 简易进程调度器 327

    17.3.1 扩展进程控制块 327

    17.3.2 就绪队列 327

    17.3.3 调度类 328

    17.3.4 简易调度器的实现 329

    17.3.5 自愿调度 330

    17.3.6 抢占调度 331

    17.3.7 测试用例 333

    17.3.8 关于调度的思考 333

    17.4 让进程运行在用户模式 335

    17.5 系统调用 338

    17.5.1 系统调用介绍 338

    17.5.2 在用户模式下调用SVC指令 338

    17.5.3 在内核模式下对系统调用的处理 339

    17.5.4 系统调用表 340

    17.6 实现clone系统调用 341

    17.7 实验 343

    17.7.1 实验17-1:进程创建 343

    17.7.2 实验17-2:进程调度 343

    17.7.3 实验17-3:让进程运行在用户模式 343

    17.7.4 实验17-4:新增一个malloc()系统调用 343

    17.7.5 实验17-5:新增一个clone()系统调用 344

    第 18章 可伸缩矢量计算与优化 345

    18.1 矢量计算基本概念 345

    18.1.1 SISD与SIMD 345

    18.1.2 定长计算与可变长矢量计算 347

    18.1.3 通道 347

    18.1.4 矢量与标量 347

    18.2 RVV寄存器 348

    18.2.1 矢量寄存器 348

    18.2.2 mstatus寄存器中的矢量上下文状态 348

    18.2.3 vtype寄存器 348

    18.2.4 vl寄存器 350

    18.2.5 vlenb寄存器 351

    18.2.6 vstart寄存器 351

    18.3 配置编译和运行环境 351

    18.3.1 搭建编译环境 351

    18.3.2 运行第 一个“hello RVV!”程序 352

    18.3.3 单步调试汇编程序 353

    18.3.4 单步调试C语言与汇编混合程序 355

    18.4 RVV指令格式 357

    18.5 配置指令 358

    18.6 加载和存储指令 360

    18.6.1 单位步长模式 360

    18.6.2 任意步长模式 363

    18.6.3 聚合加载/离散存储 364

    18.6.4 打包数据的加载与存储 365

    18.6.5 首次异常加载指令 367

    18.6.6 加载和存储全部矢量数据 368

    18.7 矢量掩码指令 369

    18.7.1 逻辑操作指令 369

    18.7.2 VCPOP.M指令 369

    18.7.3 VFIRST.M指令 370

    18.7.4 VMSBF.M指令 370

    18.7.5 VMSIF.M指令 371

    18.7.6 VMSOF.M指令 372

    18.8 矢量整型算术指令 372

    18.8.1 加宽和变窄算术指令 372

    18.8.2 加法和减法指令 373

    18.8.3 加宽模式的加法和减法指令 374

    18.8.4 位操作指令 376

    18.8.5 移位操作指令 376

    18.8.6 比较指令 376

    18.8.7 数据搬移指令 377

    18.9 案例分析18-1:使用RVV指令优化strcmp()函数 377

    18.9.1 使用纯汇编方式 378

    18.9.2 测试 379

    18.10 案例分析18-2:RGB24转BGR24 380

    18.10.1 使用C语言实现RGB24转BGR24 380

    18.10.2 使用RVV指令优化 380

    18.10.3 测试 381

    18.11 案例分析18-3:4 × 4矩阵乘法运算 382

    18.11.1 使用C语言实现4 × 4矩阵乘法运算 382

    18.11.2 使用RVV指令优化 383

    18.11.3 测试 387

    18.12 案例分析18-4:使用RVV内置函数 388

    18.13 案例分析18-5:自动矢量优化 388

    18.14 术语 390

    18.15 实验 391

    18.15.1 实验18-1:RGB24转BGR32 391

    18.15.2 实验18-2:8 × 8矩阵乘法运算 391

    18.15.3 实验18-3:使用RVV指令优化strcpy()函数 391

    18.15.4 实验18-4:使用RVV内置函数优化 391

    18.15.5 实验18-5:使用RVV优化转置矩阵的求法 392

    第 19章 压缩指令扩展 393

    19.1 RISC-V指令集的特点 393

    19.2 RVC支持的指令格式与指令编码 394

    第 20章 虚拟化扩展 396

    20.1 虚拟化技术介绍 396

    20.1.1 虚拟化技术的发展历史 396

    20.1.2 虚拟机管理程序的分类 398

    20.1.3 内存虚拟化 398

    20.1.4 I/O虚拟化 399

    20.2 RISC-V虚拟化扩展 399

    20.2.1 CPU虚拟化扩展 399

    20.2.2 M模式下系统寄存器的扩展 400

    20.2.3 HS模式下的系统寄存器 402

    20.2.4 VS模式下的系统寄存器 404

    20.3 RISC-V内存虚拟化 404

    20.4 RISC-V虚拟化扩展中的新增指令 406

    20.4.1 加载与存储虚拟机内存指令 406

    20.4.2 虚拟化内存屏障指令 406

    20.5 进入和退出虚拟机 407

    20.5.1 异常陷入 408

    20.5.2 异常返回 408

    20.5.3 新增的中断与异常类型 409

    20.6 中断虚拟化 410

    20.6.1 虚拟中断注入 410

    20.6.2 陷入与模拟 411

    20.7 案例分析20-1:进入和退出虚拟机 412

    20.7.1 进入虚拟机 413

    20.7.2 退出虚拟机 414

    20.8 案例分析20-2:建立虚拟化两阶段地址映射 415

    20.8.1 建立第二阶段的地址映射 416

    20.8.2 建立第 一阶段的地址映射 418

    20.8.3 测试 419

    20.9 案例分析20-3:在虚拟机中实现虚拟定时器 420

    20.10 案例分析20-4:在VMM中加载和存储虚拟机内存地址 422

    20.11 案例分析20-5:在VMM中模拟串口设备 424

    20.12 实验 429

    20.12.1 实验20-1:加载虚拟机1 429

    20.12.2 实验20-2:加载虚拟机2 430

    20.12.3 实验20-3:虚拟化地址映射 430

    20.12.4 实验20-4:解析虚拟机陷入的指令 430

    20.12.5 实验20-5:在VMM中模拟实现vPLIC 430

    20.12.6 实验20-6:在虚拟机中加载并运行Linux内核 430

    附录A 关于RISC-V体系结构自测题的参考答案与提示 431

    附录B RV64I指令速查表 433

    附录C RV64M指令速查表 437

    附录D RV64常用伪指令速查表 439
查看详情
相关图书 / 更多
RISC-V体系结构编程与实践
RISN—TG012-2011建设工程项目经理执业导则
住房和城乡建设部标准定额研究所 编
RISC-V体系结构编程与实践
RICH教育视野与育人模式
骆传伟、竺金飞 编
RISC-V体系结构编程与实践
RICHARD Ⅱ
威廉•莎士比亚(William Shakespeare) 著
RISC-V体系结构编程与实践
RISC-V架构嵌入式系统原理与应用——CH32V103单片机编程与项目实践
裴晓芳
RISC-V体系结构编程与实践
RISC-V嵌入式开发实践——基于CH32V307微控制器
王宜怀 杨勇 施连敏
RISC-V体系结构编程与实践
RISC-V处理器与片上系统设计----基于FPGA与云平台的实验教程
陈宏铭
RISC-V体系结构编程与实践
RIsforRussia
Vladimir Kabakov 著
RISC-V体系结构编程与实践
RISC-V架构与嵌入式开发快速入门
胡振波
RISC-V体系结构编程与实践
RINKA SLEEP STAR
梨花;RINKA
RISC-V体系结构编程与实践
RIVERA:A Revolutionary Spirit in Modern Art
Andrea Kettenmann
RISC-V体系结构编程与实践
RIA开发权威指南
路遥;蓝科;王震
RISC-V体系结构编程与实践
RINGO FILE 1998-2008
椎名林檎
您可能感兴趣 / 更多
RISC-V体系结构编程与实践
ARM64体系结构编程与实践
奔跑吧Linux社区