RISC-V Assembly Language Programming
The enthusiasm for RISC-V suggests that the architecture is a force to be reckoned with. This makes the architecture a good investment in many cases. As you take up RISC-V assembler language, you can develop optimized functions directly.
A vast number of today’s electronics projects use a microprocessor chip because of the flexibility that software control affords. But which microprocessor do you choose? Which software programming languages should be utilized? These are important questions for every project designer. RISC-V microprocessors provide extra hardware flexibility. Manufacturer costs are reduced since they don’t have IP licenses and restrictions to comply with. Without these restrictions, vendors can add custom features to their CPU, offering specialized project advantages. The well-designed RISC-V specification is organized into feature categories (referred to as extensions). This permits the vendor to choose to implement only those features that the application requires. Reducing the number of transistors on a chip results in reduced power requirements and cost.
Hobbyists and vendors alike benefit from the availability of the free Gnu C/C++ compiler toolchain. What is sometimes overlooked is that the assembler is included in the toolchain. For the most part, C/C++ will continue to be the most productive programming language. However, there sometimes remains a need for highly optimized functions attainable only with assembly language programming. One prominent area for this is the development of short interrupt service routines.
The enthusiasm for RISC-V by vendors, including Intel, suggests that the architecture is a force to be reckoned with. This makes the architecture a good investment. As you take up RISC-V assembler language, you can develop optimized functions directly. Or you can check C/C++ builds at the instruction level to see what the optimizing compiler has produced for you. Sometimes a compiler’s high-level optimization results in erroneous code. Therefore, identifying problems like this saves time.
The ESP32-C3 was chosen because of its low cost for the hobbyist and student alike. Yet, the unit is a highly functional, including USB, Wi-Fi, SPI, I2C and more. The ESP32-C3 is an excellent platform for learning about the RISC-V RV32 ISA (32-bit instruction set architecture). Espressif’s own ESP-IDF development system is used for the ESP32-C3. There are no Arduino software dependencies required.
The QEMU emulator allows the student to use their desktop computer to run Fedora Linux in the RISC-V RV64 ISA (64-bit architecture). Additionally, this environment offers the student practice at using the RISC-V floating-point extensions.
Table 1: RISC-V Basic Registers.
With a large number of registers like this, a well-constructed function can avoid reaching out to memory entirely, resulting in faster execution. The registers offer immediate access to data, whereas memory access requires additional clock cycles. All RISC-V CPUs provide these 32 registers, with one exception. Extension E for RISC-V was developed to allow manufacturers to create a CPU with only 16 registers. These are targeted to very low-cost microcontroller roles.
All registers are equally capable, with the exception of x0, which has a special talent. When x0 is specified as a source register, it supplies the integer value zero. When specified as the destination for the result, that result is discarded. Even though the remaining registers are equal in function, the Gnu calling convention reserves groups of registers for specific purposes. Examples are a0 to a7, which are used to carry arguments, t0 to t6 to hold temporary values and register ra (x1) to receive a return address.
In addition to these registers, RISC-V extensions F, D or Q add the following floating-point registers as shown in Table 2.
Table 2: Floating-point registers and their ABI Names.
The width of these registers depends upon the extensions supported. Extension F holds the C language float type, while extension D holds the double type. Finally, extension Q supports the quad floating-point format.
The observant reader may have noticed something missing. There are no status flag bits, such as Carry, Overflow, Negative, etc., and thus no combined status register. The designers of the RISC-V architecture decided that it was best to omit these. This reduces the interrupt service routine overhead because the status flags no longer require saving and restoring. RISC-V addresses that need in other ways, which is described in the book.
Hobbyists and vendors alike benefit from the availability of the free Gnu C/C++ compiler toolchain. What is sometimes overlooked is that the assembler is included in the toolchain. For the most part, C/C++ will continue to be the most productive programming language. However, there sometimes remains a need for highly optimized functions attainable only with assembly language programming. One prominent area for this is the development of short interrupt service routines.
Why Choose RISC-V for Your Project?
Many existing instruction architectures have decades of being extended so that existing software remains compatible. This pushes the software developer into a steep learning curve to master the architecture. This is tedious and can lead to longer debug times and slipped deadlines. The RISC-V specification wiped the slate clean and designed a fresh instruction set.The enthusiasm for RISC-V by vendors, including Intel, suggests that the architecture is a force to be reckoned with. This makes the architecture a good investment. As you take up RISC-V assembler language, you can develop optimized functions directly. Or you can check C/C++ builds at the instruction level to see what the optimizing compiler has produced for you. Sometimes a compiler’s high-level optimization results in erroneous code. Therefore, identifying problems like this saves time.
What Is This Book About?
The book, RISC-V Assembly Language Programming using ESP32-C3 and QEMU, is a tutorial to get you going. It is designed to be a gentle tutorial. Each chapter introduces a few minimal concepts so that you don’t need to learn too much at once. Later chapters then build on what you’ve already learned. Each project starts with a C language main program calling into one or more assembly language subprograms. This demonstrates the utility of using the C/C++ language where it makes sense to and exploiting assembly language at the same time.The ESP32-C3 was chosen because of its low cost for the hobbyist and student alike. Yet, the unit is a highly functional, including USB, Wi-Fi, SPI, I2C and more. The ESP32-C3 is an excellent platform for learning about the RISC-V RV32 ISA (32-bit instruction set architecture). Espressif’s own ESP-IDF development system is used for the ESP32-C3. There are no Arduino software dependencies required.
The QEMU emulator allows the student to use their desktop computer to run Fedora Linux in the RISC-V RV64 ISA (64-bit architecture). Additionally, this environment offers the student practice at using the RISC-V floating-point extensions.
So, What Do You Get with a RISC-V CPU?
Table 1 outlines the 32 basic integer registers that the CPU offers the programmer. These can be referred to as x0 to x31 or by the friendlier ABI (application binary interface) names, such as a0 for argument zero. For RV32 platforms like the ESP32-C3, these are 32-bit registers. For RV64 platforms, the registers are 64 bits in width instead.Table 1: RISC-V Basic Registers.
Register | ABI Name | Description |
x0 | zero | Hardwired to return zero |
x1 | ra | Return Address |
x2 | sp | Stack pointer |
x3 | gp | Global pointer |
x4 | tp | Thread pointer |
x5-x7 | t0-t2 | Temporary registers |
x8 | s0/fp | Saved register / frame pointer |
x9 | s1 | Saved register |
x10-x11 | a0-a1 | Function arguments / return value |
x12-x17 | a2-a7 | Function arguments (continued) |
x18-x27 | s2-s11 | Saved registers |
x28-x31 | t3-t6 | Temporary registers |
With a large number of registers like this, a well-constructed function can avoid reaching out to memory entirely, resulting in faster execution. The registers offer immediate access to data, whereas memory access requires additional clock cycles. All RISC-V CPUs provide these 32 registers, with one exception. Extension E for RISC-V was developed to allow manufacturers to create a CPU with only 16 registers. These are targeted to very low-cost microcontroller roles.
All registers are equally capable, with the exception of x0, which has a special talent. When x0 is specified as a source register, it supplies the integer value zero. When specified as the destination for the result, that result is discarded. Even though the remaining registers are equal in function, the Gnu calling convention reserves groups of registers for specific purposes. Examples are a0 to a7, which are used to carry arguments, t0 to t6 to hold temporary values and register ra (x1) to receive a return address.
In addition to these registers, RISC-V extensions F, D or Q add the following floating-point registers as shown in Table 2.
Table 2: Floating-point registers and their ABI Names.
Register | ABI Name | Description |
f0-f7 | ft0-ft7 | Floating-point temporaries |
f8-f9 | fs0-fs1 | Floating-point saved registers |
f10-f11 | fa0-fa1 | Floating-point arguments/return values |
f12-f17 | fa2-fa7 | Floating-point arguments |
f18-f27 | fs2-fs11 | Floating-point saved registers |
f28-f31 | ft8-ft11 | Floating-point temporaries |
The width of these registers depends upon the extensions supported. Extension F holds the C language float type, while extension D holds the double type. Finally, extension Q supports the quad floating-point format.
The observant reader may have noticed something missing. There are no status flag bits, such as Carry, Overflow, Negative, etc., and thus no combined status register. The designers of the RISC-V architecture decided that it was best to omit these. This reduces the interrupt service routine overhead because the status flags no longer require saving and restoring. RISC-V addresses that need in other ways, which is described in the book.