README.md (3999B)
1 # Biscuit: RISC-V Runtime Code Generation Library 2 3 *RISC it for the biscuit* 4 5 ## About 6 7 An experimental runtime code generator for RISC-V. 8 9 This allows for runtime code generation of RISC-V instructions. Similar 10 to how [Xbyak](https://github.com/herumi/xbyak) allows for runtime code generation of x86 instructions. 11 12 13 ## Implemented ISA Features 14 15 Includes both 32-bit and 64-bit instructions in the following: 16 17 | Feature | Version | 18 |:----------|:-------:| 19 | A | 2.1 | 20 | B | 1.0 | 21 | C | 2.0 | 22 | D | 2.2 | 23 | F | 2.2 | 24 | H | 1.0 RC | 25 | K | 1.0.1 | 26 | M | 2.0 | 27 | N | 1.1 | 28 | Q | 2.2 | 29 | RV32I | 2.1 | 30 | RV64I | 2.1 | 31 | S | 1.12 | 32 | V | 1.0 | 33 | Sstc | 0.5.4 | 34 | Zfh | 1.0 | 35 | Zfhmin | 1.0 | 36 | Zicbom | 1.0 | 37 | Zicbop | 1.0 | 38 | Zicboz | 1.0 | 39 | Zicsr | 2.0 | 40 | Zifencei | 2.0 | 41 | Zihintntl | 0.2 | 42 43 Note that usually only extensions considered ratified will be implemented 44 as non-ratified documents are considerably more likely to have 45 large changes made to them, which makes maintaining instruction 46 APIs a little annoying. 47 48 49 ## Dependencies 50 51 Biscuit requires no external dependencies for its library other than the C++ standard library. 52 The tests, however, use the Catch2 testing library. This is included in tree so there's no need 53 to worry about installing it yourself if you wish to run said tests. 54 55 56 ## Building Biscuit 57 58 1. Generate the build files for the project with CMake 59 2. Hit the build button in your IDE of choice, or run the relevant console command to build for the CMake generator you've chosen. 60 3. Done. 61 62 63 ## Running Tests 64 65 1. Generate the build files for the project with CMake 66 2. Build the tests 67 3. Run the test executable directly, or enter `ctest` into your terminal. 68 69 70 ## License 71 72 The library is licensed under the MIT license. 73 74 While it's not a requirement whatsoever, it'd be pretty neat if you told me that you found the library useful :-) 75 76 77 ## Example 78 79 The following is an adapted equivalent of the `strlen` implementation within the RISC-V bit manipulation extension specification. 80 For brevity, it has been condensed to only handle little-endian platforms. 81 82 ```cpp 83 // We prepare some contiguous buffer and give the pointer to the beginning 84 // of the data and the total size of the buffer in bytes to the assembler. 85 86 void strlen_example(uint8_t* buffer, size_t buffer_size) { 87 using namespace biscuit; 88 89 constexpr int ptrlog = 3; 90 constexpr int szreg = 8; 91 92 Assembler as(buffer, buffer_size); 93 Label done; 94 Label loop; 95 96 as.ANDI(a3, a0, szreg - 1); // Offset 97 as.ANDI(a1, a0, 0xFF8); // Align pointer 98 99 as.LI(a4, szreg); 100 as.SUB(a4, a4, a3); // XLEN - offset 101 as.SLLI(a3, a3, ptrlog); // offset * 8 102 as.LD(a2, 0, a1); // Chunk 103 104 // 105 // Shift the partial/unaligned chunk we loaded to remove the bytes 106 // from before the start of the string, adding NUL bytes at the end. 107 // 108 as.SRL(a2, a2, a3); // chunk >> (offset * 8) 109 as.ORCB(a2, a2); 110 as.NOT(a2, a2); 111 112 // Non-NUL bytes in the string have been expanded to 0x00, while 113 // NUL bytes have become 0xff. Search for the first set bit 114 // (corresponding to a NUL byte in the original chunk). 115 as.CTZ(a2, a2); 116 117 // The first chunk is special: compare against the number of valid 118 // bytes in this chunk. 119 as.SRLI(a0, a2, 3); 120 as.BGTU(a4, a0, &done); 121 as.ADDI(a3, a1, szreg); 122 as.LI(a4, -1); 123 124 // Our critical loop is 4 instructions and processes data in 4 byte 125 // or 8 byte chunks. 126 as.Bind(&loop); 127 128 as.LD(a2, szreg, a1); 129 as.ADDI(a1, a1, szreg); 130 as.ORCB(a2, a2); 131 as.BEQ(a2, a4, &loop); 132 133 as.NOT(a2, a2); 134 as.CTZ(a2, a2); 135 as.SUB(a1, a1, a3); 136 as.ADD(a0, a0, a1); 137 as.SRLI(a2, a2, 3); 138 as.ADD(a0, a0, a2); 139 140 as.Bind(&done); 141 142 as.RET(); 143 } 144 ```