# Implement computer vision algorithms with RISC-V Vector extension contributed by [Terry7Wei7](https://github.com/Terry7Wei7) # TEST 1 I found materials on RISCV Official website regarding the Running 64- and 32-bit RISC-V Linux on QEMU, and I'm attempting to follow the instructions to implement it myself ubuntu 20.04 Running 32-bit RISC-V Linux on QEMU Use Ubuntu 22.04 **Prerequisites** ```bash $sudo apt install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev \ gawk build-essential bison flex texinfo gperf libtool patchutils bc \ zlib1g-dev libexpat-dev git ``` **Getting the sources** ```bash $mkdir riscv32-linux $cd riscv32-linux ``` **Then download all the required sources, which are:** **QEMU** **Linux** **Busybox** ```bash $git clone https://github.com/qemu/qemu $git clone https://github.com/torvalds/linux $git clone https://git.busybox.net/busybox ``` **You will also need to install a RISC-V toolchain** ```bash $git clone https://github.com/riscv/riscv-gnu-toolchain $sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev ninja-build ./configure --prefix=/opt/riscv --with-arch=rv32gc --with-abi=ilp32d $make linux ``` ```bash $sudo apt-get install autoconf $sudo apt-get install automake $sudo apt-get install autotools-dev $sudo apt-get install curl $sudo apt-get install python3 $sudo apt-get install libmpc-dev $sudo apt-get install libmpfr-dev $sudo apt-get install libgmp-dev $sudo apt-get install gawk $sudo apt-get install build-essential $sudo apt-get install bison $sudo apt-get install flex $sudo apt-get install texinfo $sudo apt-get install gperf $sudo apt-get install libtool $sudo apt-get install patchutils $sudo apt-get install bc $sudo apt-get install zlib1g-dev $sudo apt-get install libexpat-dev $sudo apt-get install libnewlib-dev $sudo apt-get install device-tree-compiler ``` ```bash git clone https://github.com/riscv/riscv-gnu-toolchain cd riscv-gnu-toolchain git submodule update --init ``` **Build QEMU with the RISC-V target:** ```bash cd qemu git checkout v5.0.0 ./configure --target-list=riscv32-softmmu make -j $(nproc) sudo make install ``` **Build Linux for the RISC-V target. First, checkout to a desired version:** ```bash cd linux git checkout v5.4.0 make ARCH=riscv CROSS_COMPILE=riscv32-unknown-linux-gnu- defconfig ``` **Then compile the kernel:** ```bash make ARCH=riscv CROSS_COMPILE=riscv32-unknown-linux-gnu- -j $(nproc) ``` **Build Busybox:** ```bash cd busybox CROSS_COMPILE=riscv{{bits}}-unknown-linux-gnu- make defconfig CROSS_COMPILE=riscv{{bits}}-unknown-linux-gnu- make -j $(nproc) ``` **Go back to your main working directory and run:** ```bash sudo qemu-system-riscv32 -nographic -machine virt \ -kernel linux/arch/riscv/boot/Image -append "root=/dev/vda ro console=ttyS0" \ -drive file=busybox,format=raw,id=hd0 \ -device virtio-blk-device,drive=hd0 ``` **Problem Analyze:** I've encountered insufficient storage space, preventing me from building Linux. After addressing the space issue, I'm uncertain whether the problem lies in version compatibility or environmental configuration, causing issues with the 'make install' ref:https://risc-v-getting-started-guide.readthedocs.io/en/latest/linux-qemu.html # TEST 2 I found materials on GitHub regarding the RISC-V toolchain installation guide, and I'm attempting to follow the instructions to implement it myself ubuntu 20.04 ## Clone this repo: ```bash git clone https://github.com/johnwinans/riscv-toolchain-install-guide.git ``` ## Update the sumbodules & checkout the correct versions ```bash ./installdeps.sh ./setup.sh ``` ## Configure, build, and install the GNU toolchain and qemu (Note that this can take the better part of an hour to complete!) ```bash ./buildall.sh ``` ## Add the new tools to your PATH variable by altering your PATH If you are using bash and installed the tools in the default location then adding the following to the end of your .bashrc file will suffice: ```bash export PATH=${HOME}/projects/riscv/install/rv32i/bin:${PATH} ``` ## Give qemu a basic sanity check ```bash which qemu-system-riscv32 qemu-system-riscv32 --version qemu-system-riscv32 -machine help ``` ## Give the gnu toolchain a basic sanity check ```bash which riscv32-unknown-elf-as riscv32-unknown-elf-as --version riscv32-unknown-elf-gcc --version ``` **Problem Analyze:** I still get something issue, like encountered insufficient storage space, preventing me from building Linux,and my therminal window get close can't showoff ref:https://github.com/johnwinans/riscv-toolchain-install-guide/blob/main/README.md # Test3 I found the page ,Tony Cole provide the recommendations, and installation kit packages Risc-V Vector 32-bit v0p10 Compile/Link/Run Command Lines and Switches: ## Tools Required **Compiler used:** ```bash https://buildbot.embecosm.com/job/riscv32-clang-ubuntu1804/54/artifact/riscv32-embecosm-clang-ubuntu1804-20210509.tar.gz ``` **Linker used, this was a special build for me by Embercosm with a full library build (– thank you Embercosm):** ```bash https://buildbot.embecosm.com/job/riscv32-gcc-ubuntu1804/60/artifact/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib.tar.gz ``` **QEMU used was Git cloned from (at the time) the latest RISC-V Vector QEMU branch from SiFive:** ```bash https://github.com/sifive/qemu/tree/rvv-1.0-upstream-v7-fix ``` Follow the building instructions in the README.rst. ## Compile/Link/Run Switches **LLVM Clang Compile only:** ``` `/data/toolchains/riscv/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-cc -ffunction-sections -fdata-sections -fmacro-backtrace-limit=0 -march=rv32imafcv0p10 -mabi=ilp32f -menable-experimental-extensions -Xclang -target-feature -Xclang -experimental-zvamo -Xclang -target-feature -Xclang -experimental-zvlsseg -O2 -flax-vector-conversions -o filename.obj -c filename.c` ``` **GCC Link:** ``` `/data/tony/Toolchains/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/bin/riscv32-unknown-elf-gcc -ffunction-sections -fdata-sections -march=rv32imafc -mabi=ilp32f -Wl,--gc-sections -o filename.out filename.obj` ``` **QEMU Execute:** ``` `/data/tony/sifive/qemu/build/qemu-riscv32 -s 2048M -p 131072 -cpu rv32,x-v=true filename.out` ``` I use the GCC Linker to get printf float support in the libraries. If you don’t require library float support, then I think you may be able to just compile and link using Clang. # Sobel ``` c #include <stdio.h> #include <stdlib.h> #include <math.h> #define WIDTH 8 #define HEIGHT 8 // Define Sobel operator int sobel_operator_x[3][3] = {{-1, 0, 1}, {-2, 0, 2}, {-1, 0, 1}}; int sobel_operator_y[3][3] = {{-1, -2, -1}, {0, 0, 0}, {1, 2, 1}}; // Generate a random grayscale image matrix (3 digits) void generate_random_image(int **image, int width, int height) { for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { image[i][j] = rand() % 256; // Generate a random integer between 0 and 255 } } } // Save PGM image file void save_pgm_image(const char *filename, int **image, int width, int height) { FILE *file = fopen(filename, "w"); if (!file) { perror("Error opening file"); exit(EXIT_FAILURE); } // Write image header information fprintf(file, "P2\n%d %d\n255\n", width, height); // Write image data for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { fprintf(file, "%*d ", 3, image[i][j]); // Use a field width of 3 for output } fprintf(file, "\n"); } fclose(file); } // Perform edge detection using the Sobel operator void sobel_edge_detection(int **input_image, int **output_image, int width, int height) { int gx, gy; for (int y = 1; y < height - 1; y++) { for (int x = 1; x < width - 1; x++) { gx = (sobel_operator_x[0][0] * input_image[y - 1][x - 1]) + (sobel_operator_x[0][1] * input_image[y - 1][x]) + (sobel_operator_x[0][2] * input_image[y - 1][x + 1]) + (sobel_operator_x[1][0] * input_image[y][x - 1]) + (sobel_operator_x[1][1] * input_image[y][x]) + (sobel_operator_x[1][2] * input_image[y][x + 1]) + (sobel_operator_x[2][0] * input_image[y + 1][x - 1]) + (sobel_operator_x[2][1] * input_image[y + 1][x]) + (sobel_operator_x[2][2] * input_image[y + 1][x + 1]); gy = (sobel_operator_y[0][0] * input_image[y - 1][x - 1]) + (sobel_operator_y[0][1] * input_image[y - 1][x]) + (sobel_operator_y[0][2] * input_image[y - 1][x + 1]) + (sobel_operator_y[1][0] * input_image[y][x - 1]) + (sobel_operator_y[1][1] * input_image[y][x]) + (sobel_operator_y[1][2] * input_image[y][x + 1]) + (sobel_operator_y[2][0] * input_image[y + 1][x - 1]) + (sobel_operator_y[2][1] * input_image[y + 1][x]) + (sobel_operator_y[2][2] * input_image[y + 1][x + 1]); // Normalize gradient magnitude output_image[y][x] = (int)sqrt((double)(gx * gx + gy * gy)) / 4; // Divide by 4 for normalization } } } int main() { int **input_image, **output_image; // Allocate memory and generate a random grayscale value matrix input_image = (int **)malloc(sizeof(int *) * HEIGHT); for (int i = 0; i < HEIGHT; i++) { input_image[i] = (int *)malloc(sizeof(int) * WIDTH); } generate_random_image(input_image, WIDTH, HEIGHT); // Allocate memory for the output image output_image = (int **)malloc(sizeof(int *) * HEIGHT); for (int i = 0; i < HEIGHT; i++) { output_image[i] = (int *)malloc(sizeof(int) * WIDTH); } // Output the original image to the terminal printf("Original Image:\n"); for (int i = 0; i < HEIGHT; i++) { for (int j = 0; j < WIDTH; j++) { printf("%3d ", input_image[i][j]); } printf("\n"); } printf("\n"); // Perform Sobel edge detection sobel_edge_detection(input_image, output_image, WIDTH, HEIGHT); // Output the Sobel-processed image to the terminal printf("Sobel Result:\n"); for (int i = 0; i < HEIGHT; i++) { for (int j = 0; j < WIDTH; j++) { printf("%3d ", output_image[i][j]); } printf("\n"); } // Free memory for (int i = 0; i < HEIGHT; i++) { free(input_image[i]); free(output_image[i]); } free(input_image); free(output_image); return 0; } ``` ``` bash terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-clang -march=rv32ima -mabi=ilp32 -o sobel.elf sobel.c --sysroot=/home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/riscv32-unknown-elf -L/home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/riscv32-unknown-elf/lib -lc -lgloss -lm terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-size sobel.elf text data bss dec hex filename 25084 352 56 25492 6394 sobel.elf terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-readelf -h sobel.elf ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: RISC-V Version: 0x1 Entry point address: 0x10094 Start of program headers: 52 (bytes into file) Start of section headers: 380812 (bytes into file) Flags: 0x1, RVC, soft-float ABI Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 3 Size of section headers: 40 (bytes) Number of section headers: 24 Section header string table index: 23 ``` **running at qemu** ``` terry@ubuntu:~/qemu$ qemu-riscv32 ./sobel.elf Original Image: 45 207 70 41 4 180 120 216 104 167 255 63 43 241 252 217 122 150 9 44 165 87 116 100 196 175 21 40 164 233 87 219 94 32 251 56 168 78 166 20 147 37 86 36 68 223 89 141 67 123 190 144 22 137 157 126 119 198 47 38 152 136 245 180 Sobel Result: 0 0 0 0 0 0 0 0 0 58 127 87 146 121 54 0 0 69 165 72 125 17 84 0 0 76 129 112 112 51 18 0 0 67 22 14 117 32 57 0 0 45 17 72 103 44 68 0 0 69 36 63 70 97 67 0 0 0 0 0 0 0 0 0 ``` ```bash terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-clang -S -march=rv32ima -mabi=ilp32 -o sobel.S sobel.c ``` :::spoiler **assembly** ``` assembly .text .attribute 4, 16 .attribute 5, "rv32i2p0_m2p0_a2p0" .file "sobel.c" .globl generate_random_image # -- Begin function generate_random_image .p2align 2 .type generate_random_image,@function generate_random_image: # @generate_random_image # %bb.0: addi sp, sp, -32 sw ra, 28(sp) # 4-byte Folded Spill sw s0, 24(sp) # 4-byte Folded Spill addi s0, sp, 32 sw a0, -12(s0) sw a1, -16(s0) sw a2, -20(s0) mv a0, zero sw a0, -24(s0) j .LBB0_1 .LBB0_1: # =>This Loop Header: Depth=1 # Child Loop BB0_3 Depth 2 lw a0, -24(s0) lw a1, -20(s0) bge a0, a1, .LBB0_8 j .LBB0_2 .LBB0_2: # in Loop: Header=BB0_1 Depth=1 mv a0, zero sw a0, -28(s0) j .LBB0_3 .LBB0_3: # Parent Loop BB0_1 Depth=1 # => This Inner Loop Header: Depth=2 lw a0, -28(s0) lw a1, -16(s0) bge a0, a1, .LBB0_6 j .LBB0_4 .LBB0_4: # in Loop: Header=BB0_3 Depth=2 call rand srai a1, a0, 31 srli a1, a1, 24 add a1, a0, a1 andi a1, a1, -256 sub a0, a0, a1 lw a1, -12(s0) lw a2, -24(s0) slli a2, a2, 2 add a1, a1, a2 lw a1, 0(a1) lw a2, -28(s0) slli a2, a2, 2 add a1, a1, a2 sw a0, 0(a1) j .LBB0_5 .LBB0_5: # in Loop: Header=BB0_3 Depth=2 lw a0, -28(s0) addi a0, a0, 1 sw a0, -28(s0) j .LBB0_3 .LBB0_6: # in Loop: Header=BB0_1 Depth=1 j .LBB0_7 .LBB0_7: # in Loop: Header=BB0_1 Depth=1 lw a0, -24(s0) addi a0, a0, 1 sw a0, -24(s0) j .LBB0_1 .LBB0_8: lw s0, 24(sp) # 4-byte Folded Reload lw ra, 28(sp) # 4-byte Folded Reload addi sp, sp, 32 ret .Lfunc_end0: .size generate_random_image, .Lfunc_end0-generate_random_image # -- End function .globl save_pgm_image # -- Begin function save_pgm_image .p2align 2 .type save_pgm_image,@function save_pgm_image: # @save_pgm_image # %bb.0: addi sp, sp, -48 sw ra, 44(sp) # 4-byte Folded Spill sw s0, 40(sp) # 4-byte Folded Spill addi s0, sp, 48 sw a0, -12(s0) sw a1, -16(s0) sw a2, -20(s0) sw a3, -24(s0) lw a0, -12(s0) lui a1, %hi(.L.str) addi a1, a1, %lo(.L.str) call fopen sw a0, -28(s0) lw a0, -28(s0) mv a1, zero bne a0, a1, .LBB1_2 j .LBB1_1 .LBB1_1: lui a0, %hi(.L.str.1) addi a0, a0, %lo(.L.str.1) call perror addi a0, zero, 1 call exit .LBB1_2: lw a0, -28(s0) lw a2, -20(s0) lw a3, -24(s0) lui a1, %hi(.L.str.2) addi a1, a1, %lo(.L.str.2) call fprintf mv a0, zero sw a0, -32(s0) j .LBB1_3 .LBB1_3: # =>This Loop Header: Depth=1 # Child Loop BB1_5 Depth 2 lw a0, -32(s0) lw a1, -24(s0) bge a0, a1, .LBB1_10 j .LBB1_4 .LBB1_4: # in Loop: Header=BB1_3 Depth=1 mv a0, zero sw a0, -36(s0) j .LBB1_5 .LBB1_5: # Parent Loop BB1_3 Depth=1 # => This Inner Loop Header: Depth=2 lw a0, -36(s0) lw a1, -20(s0) bge a0, a1, .LBB1_8 j .LBB1_6 .LBB1_6: # in Loop: Header=BB1_5 Depth=2 lw a0, -28(s0) lw a1, -16(s0) lw a2, -32(s0) slli a2, a2, 2 add a1, a1, a2 lw a1, 0(a1) lw a2, -36(s0) slli a2, a2, 2 add a1, a1, a2 lw a3, 0(a1) lui a1, %hi(.L.str.3) addi a1, a1, %lo(.L.str.3) addi a2, zero, 3 call fprintf j .LBB1_7 .LBB1_7: # in Loop: Header=BB1_5 Depth=2 lw a0, -36(s0) addi a0, a0, 1 sw a0, -36(s0) j .LBB1_5 .LBB1_8: # in Loop: Header=BB1_3 Depth=1 lw a0, -28(s0) lui a1, %hi(.L.str.4) addi a1, a1, %lo(.L.str.4) call fprintf j .LBB1_9 .LBB1_9: # in Loop: Header=BB1_3 Depth=1 lw a0, -32(s0) addi a0, a0, 1 sw a0, -32(s0) j .LBB1_3 .LBB1_10: lw a0, -28(s0) call fclose lw s0, 40(sp) # 4-byte Folded Reload lw ra, 44(sp) # 4-byte Folded Reload addi sp, sp, 48 ret .Lfunc_end1: .size save_pgm_image, .Lfunc_end1-save_pgm_image # -- End function .globl sobel_edge_detection # -- Begin function sobel_edge_detection .p2align 2 .type sobel_edge_detection,@function sobel_edge_detection: # @sobel_edge_detection # %bb.0: addi sp, sp, -48 sw ra, 44(sp) # 4-byte Folded Spill sw s0, 40(sp) # 4-byte Folded Spill addi s0, sp, 48 sw a0, -12(s0) sw a1, -16(s0) sw a2, -20(s0) sw a3, -24(s0) addi a0, zero, 1 sw a0, -36(s0) j .LBB2_1 .LBB2_1: # =>This Loop Header: Depth=1 # Child Loop BB2_3 Depth 2 lw a0, -36(s0) lw a1, -24(s0) addi a1, a1, -1 bge a0, a1, .LBB2_8 j .LBB2_2 .LBB2_2: # in Loop: Header=BB2_1 Depth=1 addi a0, zero, 1 sw a0, -40(s0) j .LBB2_3 .LBB2_3: # Parent Loop BB2_1 Depth=1 # => This Inner Loop Header: Depth=2 lw a0, -40(s0) lw a1, -20(s0) addi a1, a1, -1 bge a0, a1, .LBB2_6 j .LBB2_4 .LBB2_4: # in Loop: Header=BB2_3 Depth=2 lui a1, %hi(sobel_operator_x) lw a0, %lo(sobel_operator_x)(a1) lw a2, -12(s0) lw a3, -36(s0) slli a3, a3, 2 add a2, a2, a3 lw a7, -4(a2) lw a3, -40(s0) slli a5, a3, 2 addi a6, a5, -4 add a3, a7, a6 lw a3, 0(a3) mul a0, a0, a3 addi a1, a1, %lo(sobel_operator_x) sw a1, -48(s0) # 4-byte Folded Spill lw a3, 4(a1) add a4, a7, a5 lw a4, 0(a4) mul a3, a3, a4 add a0, a0, a3 lw a4, 8(a1) addi a3, a5, 4 add a7, a7, a3 lw a7, 0(a7) mul a4, a4, a7 add a0, a0, a4 lw a4, 12(a1) lw a7, 0(a2) add t0, a7, a6 lw t0, 0(t0) mul a4, a4, t0 add a0, a0, a4 lw a4, 16(a1) add t0, a7, a5 lw t0, 0(t0) mul a4, a4, t0 add a0, a0, a4 lw a4, 20(a1) add a7, a7, a3 lw a7, 0(a7) mul a4, a4, a7 add a0, a0, a4 lw a4, 24(a1) lw a2, 4(a2) add a6, a2, a6 lw a6, 0(a6) mul a4, a4, a6 add a0, a0, a4 lw a4, 28(a1) add a5, a2, a5 lw a5, 0(a5) mul a4, a4, a5 add a0, a0, a4 lw a1, 32(a1) add a2, a2, a3 lw a2, 0(a2) mul a1, a1, a2 add a0, a0, a1 sw a0, -28(s0) lui a1, %hi(sobel_operator_y) lw a0, %lo(sobel_operator_y)(a1) lw a2, -12(s0) lw a3, -36(s0) slli a3, a3, 2 add a2, a2, a3 lw a7, -4(a2) lw a3, -40(s0) slli a5, a3, 2 addi a6, a5, -4 add a3, a7, a6 lw a3, 0(a3) mul a0, a0, a3 addi a1, a1, %lo(sobel_operator_y) sw a1, -44(s0) # 4-byte Folded Spill lw a3, 4(a1) add a4, a7, a5 lw a4, 0(a4) mul a3, a3, a4 add a0, a0, a3 lw a4, 8(a1) addi a3, a5, 4 add a7, a7, a3 lw a7, 0(a7) mul a4, a4, a7 add a0, a0, a4 lw a4, 12(a1) lw a7, 0(a2) add t0, a7, a6 lw t0, 0(t0) mul a4, a4, t0 add a0, a0, a4 lw a4, 16(a1) add t0, a7, a5 lw t0, 0(t0) mul a4, a4, t0 add a0, a0, a4 lw a4, 20(a1) add a7, a7, a3 lw a7, 0(a7) mul a4, a4, a7 add a0, a0, a4 lw a4, 24(a1) lw a2, 4(a2) add a6, a2, a6 lw a6, 0(a6) mul a4, a4, a6 add a0, a0, a4 lw a4, 28(a1) add a5, a2, a5 lw a5, 0(a5) mul a4, a4, a5 add a0, a0, a4 lw a1, 32(a1) add a2, a2, a3 lw a2, 0(a2) mul a1, a1, a2 add a0, a0, a1 sw a0, -32(s0) lw a0, -28(s0) mul a0, a0, a0 lw a1, -32(s0) mul a1, a1, a1 add a0, a0, a1 call __floatsidf@plt call sqrt call __fixdfsi@plt srai a1, a0, 31 srli a1, a1, 30 add a0, a0, a1 srai a0, a0, 2 lw a1, -16(s0) lw a2, -36(s0) slli a2, a2, 2 add a1, a1, a2 lw a1, 0(a1) lw a2, -40(s0) slli a2, a2, 2 add a1, a1, a2 sw a0, 0(a1) j .LBB2_5 .LBB2_5: # in Loop: Header=BB2_3 Depth=2 lw a0, -40(s0) addi a0, a0, 1 sw a0, -40(s0) j .LBB2_3 .LBB2_6: # in Loop: Header=BB2_1 Depth=1 j .LBB2_7 .LBB2_7: # in Loop: Header=BB2_1 Depth=1 lw a0, -36(s0) addi a0, a0, 1 sw a0, -36(s0) j .LBB2_1 .LBB2_8: lw s0, 40(sp) # 4-byte Folded Reload lw ra, 44(sp) # 4-byte Folded Reload addi sp, sp, 48 ret .Lfunc_end2: .size sobel_edge_detection, .Lfunc_end2-sobel_edge_detection # -- End function .globl main # -- Begin function main .p2align 2 .type main,@function main: # @main # %bb.0: addi sp, sp, -48 sw ra, 44(sp) # 4-byte Folded Spill sw s0, 40(sp) # 4-byte Folded Spill addi s0, sp, 48 mv a0, zero sw a0, -36(s0) # 4-byte Folded Spill sw a0, -12(s0) addi a0, zero, 128 call malloc mv a1, a0 lw a0, -36(s0) # 4-byte Folded Reload sw a1, -16(s0) sw a0, -24(s0) j .LBB3_1 .LBB3_1: # =>This Inner Loop Header: Depth=1 lw a1, -24(s0) addi a0, zero, 31 blt a0, a1, .LBB3_4 j .LBB3_2 .LBB3_2: # in Loop: Header=BB3_1 Depth=1 addi a0, zero, 128 call malloc lw a1, -16(s0) lw a2, -24(s0) slli a2, a2, 2 add a1, a1, a2 sw a0, 0(a1) j .LBB3_3 .LBB3_3: # in Loop: Header=BB3_1 Depth=1 lw a0, -24(s0) addi a0, a0, 1 sw a0, -24(s0) j .LBB3_1 .LBB3_4: lw a0, -16(s0) addi a2, zero, 32 mv a1, a2 call generate_random_image addi a0, zero, 128 call malloc sw a0, -20(s0) mv a0, zero sw a0, -28(s0) j .LBB3_5 .LBB3_5: # =>This Inner Loop Header: Depth=1 lw a1, -28(s0) addi a0, zero, 31 blt a0, a1, .LBB3_8 j .LBB3_6 .LBB3_6: # in Loop: Header=BB3_5 Depth=1 addi a0, zero, 128 call malloc lw a1, -20(s0) lw a2, -28(s0) slli a2, a2, 2 add a1, a1, a2 sw a0, 0(a1) j .LBB3_7 .LBB3_7: # in Loop: Header=BB3_5 Depth=1 lw a0, -28(s0) addi a0, a0, 1 sw a0, -28(s0) j .LBB3_5 .LBB3_8: lw a1, -16(s0) lui a0, %hi(.L.str.5) addi a0, a0, %lo(.L.str.5) addi a3, zero, 32 sw a3, -40(s0) # 4-byte Folded Spill mv a2, a3 call save_pgm_image lw a3, -40(s0) # 4-byte Folded Reload lw a0, -16(s0) lw a1, -20(s0) mv a2, a3 call sobel_edge_detection lw a3, -40(s0) # 4-byte Folded Reload lw a1, -20(s0) lui a0, %hi(.L.str.6) addi a0, a0, %lo(.L.str.6) mv a2, a3 call save_pgm_image mv a0, zero sw a0, -32(s0) j .LBB3_9 .LBB3_9: # =>This Inner Loop Header: Depth=1 lw a1, -32(s0) addi a0, zero, 31 blt a0, a1, .LBB3_12 j .LBB3_10 .LBB3_10: # in Loop: Header=BB3_9 Depth=1 lw a0, -16(s0) lw a1, -32(s0) slli a1, a1, 2 add a0, a0, a1 lw a0, 0(a0) call free lw a0, -20(s0) lw a1, -32(s0) slli a1, a1, 2 add a0, a0, a1 lw a0, 0(a0) call free j .LBB3_11 .LBB3_11: # in Loop: Header=BB3_9 Depth=1 lw a0, -32(s0) addi a0, a0, 1 sw a0, -32(s0) j .LBB3_9 .LBB3_12: lw a0, -16(s0) call free lw a0, -20(s0) call free mv a0, zero lw s0, 40(sp) # 4-byte Folded Reload lw ra, 44(sp) # 4-byte Folded Reload addi sp, sp, 48 ret .Lfunc_end3: .size main, .Lfunc_end3-main # -- End function .type sobel_operator_x,@object # @sobel_operator_x .data .globl sobel_operator_x .p2align 2 sobel_operator_x: .word 4294967295 # 0xffffffff .word 0 # 0x0 .word 1 # 0x1 .word 4294967294 # 0xfffffffe .word 0 # 0x0 .word 2 # 0x2 .word 4294967295 # 0xffffffff .word 0 # 0x0 .word 1 # 0x1 .size sobel_operator_x, 36 .type sobel_operator_y,@object # @sobel_operator_y .globl sobel_operator_y .p2align 2 sobel_operator_y: .word 4294967295 # 0xffffffff .word 4294967294 # 0xfffffffe .word 4294967295 # 0xffffffff .zero 12 .word 1 # 0x1 .word 2 # 0x2 .word 1 # 0x1 .size sobel_operator_y, 36 .type .L.str,@object # @.str .section .rodata.str1.1,"aMS",@progbits,1 .L.str: .asciz "w" .size .L.str, 2 .type .L.str.1,@object # @.str.1 .L.str.1: .asciz "Error opening file" .size .L.str.1, 19 .type .L.str.2,@object # @.str.2 .L.str.2: .asciz "P2\n%d %d\n255\n" .size .L.str.2, 14 .type .L.str.3,@object # @.str.3 .L.str.3: .asciz "%*d " .size .L.str.3, 5 .type .L.str.4,@object # @.str.4 .L.str.4: .asciz "\n" .size .L.str.4, 2 .type .L.str.5,@object # @.str.5 .L.str.5: .asciz "original.pgm" .size .L.str.5, 13 .type .L.str.6,@object # @.str.6 .L.str.6: .asciz "sobel_result.pgm" .size .L.str.6, 17 .ident "riscv32-embecosm-clang-ubuntu1804-20210509 clang version 13.0.0 (https://mirrors.git.embecosm.com/mirrors/llvm-project.git 4aec8f4ce0f564aa68c23b9e29c2e3a945eec947)" .section ".note.GNU-stack","",@progbits .addrsig .addrsig_sym generate_random_image .addrsig_sym rand .addrsig_sym save_pgm_image .addrsig_sym fopen .addrsig_sym perror .addrsig_sym exit .addrsig_sym fprintf .addrsig_sym fclose .addrsig_sym sobel_edge_detection .addrsig_sym sqrt .addrsig_sym malloc .addrsig_sym free .addrsig_sym sobel_operator_x .addrsig_sym sobel_operator_y ``` ::: # Gaussian Blur ``` c #include <stdio.h> #define WIDTH 5 #define HEIGHT 5 // Image data int image[WIDTH][HEIGHT] = { {120, 50, 200, 30, 80}, {90, 180, 60, 40, 140}, {70, 20, 110, 10, 160}, {130, 100, 150, 190, 220}, {30, 80, 120, 50, 200} }; // Gaussian kernel float gaussian_kernel[3][3] = { {1.0 / 16, 2.0 / 16, 1.0 / 16}, {2.0 / 16, 4.0 / 16, 2.0 / 16}, {1.0 / 16, 2.0 / 16, 1.0 / 16} }; // Gaussian blur function void gaussian_blur() { int blurred_image[WIDTH][HEIGHT]; for (int i = 1; i < WIDTH - 1; i++) { for (int j = 1; j < HEIGHT - 1; j++) { // Perform convolution float sum = 0.0; for (int m = -1; m <= 1; m++) { for (int n = -1; n <= 1; n++) { sum += image[i + m][j + n] * gaussian_kernel[m + 1][n + 1]; } } // Round and store the result blurred_image[i][j] = (int)(sum + 0.5); } } // Output the original image printf("Original Image:\n"); for (int i = 0; i < WIDTH; i++) { for (int j = 0; j < HEIGHT; j++) { printf("%d ", image[i][j]); } printf("\n"); } // Output the image after Gaussian blur printf("\nBlurred Image:\n"); for (int i = 0; i < WIDTH; i++) { for (int j = 0; j < HEIGHT; j++) { printf("%d ", blurred_image[i][j]); } printf("\n"); } } int main() { // Perform Gaussian blur gaussian_blur(); return 0; } ``` ``` bash terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-clang -march=rv32ima -mabi=ilp32 -o gaussian.elf gaussian.c --sysroot=/home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/riscv32-unknown-elf -L/home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/riscv32-unknown-elf/lib -lc -lgloss -lm terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-size gaussian.elf text data bss dec hex filename 15322 416 56 15794 3db2 gaussian.elf terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-readelf -h gaussian.elf ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: RISC-V Version: 0x1 Entry point address: 0x10094 Start of program headers: 52 (bytes into file) Start of section headers: 266440 (bytes into file) Flags: 0x1, RVC, soft-float ABI Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 3 Size of section headers: 40 (bytes) Number of section headers: 24 Section header string table index: 23 ``` **running at qemu** ``` terry@ubuntu:~/qemu$ qemu-riscv32 ./gaussian.elf Original Image: 120 50 200 30 80 90 180 60 40 140 70 20 110 10 160 130 100 150 190 220 30 80 120 50 200 Blurred Image: 0 0 0 0 0 0 104 88 74 0 0 89 89 101 0 0 93 113 138 0 0 0 0 0 0 ``` ```bash terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-clang -S -march=rv32ima -mabi=ilp32 -o gaussian.S gaussian.c ``` :::spoiler **assembly** ```assembly .text .attribute 4, 16 .attribute 5, "rv32i2p0_m2p0_a2p0" .file "gaussian.c" .globl gaussian_blur # -- Begin function gaussian_blur .p2align 2 .type gaussian_blur,@function gaussian_blur: # @gaussian_blur # %bb.0: addi sp, sp, -160 sw ra, 156(sp) # 4-byte Folded Spill sw s0, 152(sp) # 4-byte Folded Spill addi s0, sp, 160 addi a0, zero, 1 sw a0, -112(s0) j .LBB0_1 .LBB0_1: # =>This Loop Header: Depth=1 # Child Loop BB0_3 Depth 2 # Child Loop BB0_5 Depth 3 # Child Loop BB0_7 Depth 4 lw a1, -112(s0) addi a0, zero, 3 blt a0, a1, .LBB0_16 j .LBB0_2 .LBB0_2: # in Loop: Header=BB0_1 Depth=1 addi a0, zero, 1 sw a0, -116(s0) j .LBB0_3 .LBB0_3: # Parent Loop BB0_1 Depth=1 # => This Loop Header: Depth=2 # Child Loop BB0_5 Depth 3 # Child Loop BB0_7 Depth 4 lw a1, -116(s0) addi a0, zero, 3 blt a0, a1, .LBB0_14 j .LBB0_4 .LBB0_4: # in Loop: Header=BB0_3 Depth=2 mv a0, zero sw a0, -120(s0) addi a0, zero, -1 sw a0, -124(s0) j .LBB0_5 .LBB0_5: # Parent Loop BB0_1 Depth=1 # Parent Loop BB0_3 Depth=2 # => This Loop Header: Depth=3 # Child Loop BB0_7 Depth 4 lw a1, -124(s0) addi a0, zero, 1 blt a0, a1, .LBB0_12 j .LBB0_6 .LBB0_6: # in Loop: Header=BB0_5 Depth=3 addi a0, zero, -1 sw a0, -128(s0) j .LBB0_7 .LBB0_7: # Parent Loop BB0_1 Depth=1 # Parent Loop BB0_3 Depth=2 # Parent Loop BB0_5 Depth=3 # => This Inner Loop Header: Depth=4 lw a1, -128(s0) addi a0, zero, 1 blt a0, a1, .LBB0_10 j .LBB0_8 .LBB0_8: # in Loop: Header=BB0_7 Depth=4 lw a0, -112(s0) lw a1, -124(s0) sw a1, -152(s0) # 4-byte Folded Spill add a0, a0, a1 addi a1, zero, 20 mul a0, a0, a1 lw a1, -116(s0) lw a2, -128(s0) sw a2, -148(s0) # 4-byte Folded Spill add a1, a1, a2 slli a1, a1, 2 add a0, a0, a1 lui a1, %hi(image) addi a1, a1, %lo(image) add a0, a0, a1 lw a0, 0(a0) call __floatsisf@plt lw a1, -152(s0) # 4-byte Folded Reload lw a2, -148(s0) # 4-byte Folded Reload addi a3, zero, 12 mul a1, a1, a3 slli a2, a2, 2 add a2, a1, a2 lui a1, %hi(gaussian_kernel) addi a1, a1, %lo(gaussian_kernel) add a1, a1, a2 lw a1, 16(a1) call __mulsf3@plt mv a1, a0 lw a0, -120(s0) call __addsf3@plt sw a0, -120(s0) j .LBB0_9 .LBB0_9: # in Loop: Header=BB0_7 Depth=4 lw a0, -128(s0) addi a0, a0, 1 sw a0, -128(s0) j .LBB0_7 .LBB0_10: # in Loop: Header=BB0_5 Depth=3 j .LBB0_11 .LBB0_11: # in Loop: Header=BB0_5 Depth=3 lw a0, -124(s0) addi a0, a0, 1 sw a0, -124(s0) j .LBB0_5 .LBB0_12: # in Loop: Header=BB0_3 Depth=2 lw a0, -120(s0) call __extendsfdf2@plt mv a2, zero lui a3, 261632 call __adddf3@plt call __fixdfsi@plt lw a1, -112(s0) addi a2, zero, 20 mul a2, a1, a2 addi a1, s0, -108 add a1, a1, a2 lw a2, -116(s0) slli a2, a2, 2 add a1, a1, a2 sw a0, 0(a1) j .LBB0_13 .LBB0_13: # in Loop: Header=BB0_3 Depth=2 lw a0, -116(s0) addi a0, a0, 1 sw a0, -116(s0) j .LBB0_3 .LBB0_14: # in Loop: Header=BB0_1 Depth=1 j .LBB0_15 .LBB0_15: # in Loop: Header=BB0_1 Depth=1 lw a0, -112(s0) addi a0, a0, 1 sw a0, -112(s0) j .LBB0_1 .LBB0_16: lui a0, %hi(.L.str) addi a0, a0, %lo(.L.str) call printf mv a0, zero sw a0, -132(s0) j .LBB0_17 .LBB0_17: # =>This Loop Header: Depth=1 # Child Loop BB0_19 Depth 2 lw a1, -132(s0) addi a0, zero, 4 blt a0, a1, .LBB0_24 j .LBB0_18 .LBB0_18: # in Loop: Header=BB0_17 Depth=1 mv a0, zero sw a0, -136(s0) j .LBB0_19 .LBB0_19: # Parent Loop BB0_17 Depth=1 # => This Inner Loop Header: Depth=2 lw a1, -136(s0) addi a0, zero, 4 blt a0, a1, .LBB0_22 j .LBB0_20 .LBB0_20: # in Loop: Header=BB0_19 Depth=2 lw a0, -132(s0) addi a1, zero, 20 mul a0, a0, a1 lw a1, -136(s0) slli a1, a1, 2 add a0, a0, a1 lui a1, %hi(image) addi a1, a1, %lo(image) add a0, a0, a1 lw a1, 0(a0) lui a0, %hi(.L.str.1) addi a0, a0, %lo(.L.str.1) call printf j .LBB0_21 .LBB0_21: # in Loop: Header=BB0_19 Depth=2 lw a0, -136(s0) addi a0, a0, 1 sw a0, -136(s0) j .LBB0_19 .LBB0_22: # in Loop: Header=BB0_17 Depth=1 lui a0, %hi(.L.str.2) addi a0, a0, %lo(.L.str.2) call printf j .LBB0_23 .LBB0_23: # in Loop: Header=BB0_17 Depth=1 lw a0, -132(s0) addi a0, a0, 1 sw a0, -132(s0) j .LBB0_17 .LBB0_24: lui a0, %hi(.L.str.3) addi a0, a0, %lo(.L.str.3) call printf mv a0, zero sw a0, -140(s0) j .LBB0_25 .LBB0_25: # =>This Loop Header: Depth=1 # Child Loop BB0_27 Depth 2 lw a1, -140(s0) addi a0, zero, 4 blt a0, a1, .LBB0_32 j .LBB0_26 .LBB0_26: # in Loop: Header=BB0_25 Depth=1 mv a0, zero sw a0, -144(s0) j .LBB0_27 .LBB0_27: # Parent Loop BB0_25 Depth=1 # => This Inner Loop Header: Depth=2 lw a1, -144(s0) addi a0, zero, 4 blt a0, a1, .LBB0_30 j .LBB0_28 .LBB0_28: # in Loop: Header=BB0_27 Depth=2 lw a0, -140(s0) addi a1, zero, 20 mul a1, a0, a1 addi a0, s0, -108 add a0, a0, a1 lw a1, -144(s0) slli a1, a1, 2 add a0, a0, a1 lw a1, 0(a0) lui a0, %hi(.L.str.1) addi a0, a0, %lo(.L.str.1) call printf j .LBB0_29 .LBB0_29: # in Loop: Header=BB0_27 Depth=2 lw a0, -144(s0) addi a0, a0, 1 sw a0, -144(s0) j .LBB0_27 .LBB0_30: # in Loop: Header=BB0_25 Depth=1 lui a0, %hi(.L.str.2) addi a0, a0, %lo(.L.str.2) call printf j .LBB0_31 .LBB0_31: # in Loop: Header=BB0_25 Depth=1 lw a0, -140(s0) addi a0, a0, 1 sw a0, -140(s0) j .LBB0_25 .LBB0_32: lw s0, 152(sp) # 4-byte Folded Reload lw ra, 156(sp) # 4-byte Folded Reload addi sp, sp, 160 ret .Lfunc_end0: .size gaussian_blur, .Lfunc_end0-gaussian_blur # -- End function .globl main # -- Begin function main .p2align 2 .type main,@function main: # @main # %bb.0: addi sp, sp, -16 sw ra, 12(sp) # 4-byte Folded Spill sw s0, 8(sp) # 4-byte Folded Spill addi s0, sp, 16 mv a0, zero sw a0, -16(s0) # 4-byte Folded Spill sw a0, -12(s0) call gaussian_blur lw a0, -16(s0) # 4-byte Folded Reload lw s0, 8(sp) # 4-byte Folded Reload lw ra, 12(sp) # 4-byte Folded Reload addi sp, sp, 16 ret .Lfunc_end1: .size main, .Lfunc_end1-main # -- End function .type image,@object # @image .data .globl image .p2align 2 image: .word 120 # 0x78 .word 50 # 0x32 .word 200 # 0xc8 .word 30 # 0x1e .word 80 # 0x50 .word 90 # 0x5a .word 180 # 0xb4 .word 60 # 0x3c .word 40 # 0x28 .word 140 # 0x8c .word 70 # 0x46 .word 20 # 0x14 .word 110 # 0x6e .word 10 # 0xa .word 160 # 0xa0 .word 130 # 0x82 .word 100 # 0x64 .word 150 # 0x96 .word 190 # 0xbe .word 220 # 0xdc .word 30 # 0x1e .word 80 # 0x50 .word 120 # 0x78 .word 50 # 0x32 .word 200 # 0xc8 .size image, 100 .type gaussian_kernel,@object # @gaussian_kernel .globl gaussian_kernel .p2align 2 gaussian_kernel: .word 0x3d800000 # float 0.0625 .word 0x3e000000 # float 0.125 .word 0x3d800000 # float 0.0625 .word 0x3e000000 # float 0.125 .word 0x3e800000 # float 0.25 .word 0x3e000000 # float 0.125 .word 0x3d800000 # float 0.0625 .word 0x3e000000 # float 0.125 .word 0x3d800000 # float 0.0625 .size gaussian_kernel, 36 .type .L.str,@object # @.str .section .rodata.str1.1,"aMS",@progbits,1 .L.str: .asciz "Original Image:\n" .size .L.str, 17 .type .L.str.1,@object # @.str.1 .L.str.1: .asciz "%d " .size .L.str.1, 4 .type .L.str.2,@object # @.str.2 .L.str.2: .asciz "\n" .size .L.str.2, 2 .type .L.str.3,@object # @.str.3 .L.str.3: .asciz "\nBlurred Image:\n" .size .L.str.3, 17 .ident "riscv32-embecosm-clang-ubuntu1804-20210509 clang version 13.0.0 (https://mirrors.git.embecosm.com/mirrors/llvm-project.git 4aec8f4ce0f564aa68c23b9e29c2e3a945eec947)" .section ".note.GNU-stack","",@progbits .addrsig .addrsig_sym gaussian_blur .addrsig_sym printf .addrsig_sym image .addrsig_sym gaussian_kernel ``` ::: # Histogram Equalization ``` c #include <stdio.h> #include <stdlib.h> #define WIDTH 5 #define HEIGHT 5 #define MAX_PIXEL_VALUE 255 // Image data int image[WIDTH][HEIGHT] = { {120, 50, 200, 30, 80}, {90, 180, 60, 40, 140}, {70, 20, 110, 10, 160}, {130, 100, 150, 190, 220}, {30, 80, 120, 50, 200} }; // Function for histogram equalization void histogram_equalization() { // Compute the histogram int histogram[MAX_PIXEL_VALUE + 1] = {0}; for (int i = 0; i < WIDTH; i++) { for (int j = 0; j < HEIGHT; j++) { histogram[image[i][j]]++; } } // Compute the cumulative histogram int cumulative_histogram[MAX_PIXEL_VALUE + 1] = {0}; cumulative_histogram[0] = histogram[0]; for (int i = 1; i <= MAX_PIXEL_VALUE; i++) { cumulative_histogram[i] = cumulative_histogram[i - 1] + histogram[i]; } // Compute the equalized pixel values int equalized_image[WIDTH][HEIGHT]; for (int i = 0; i < WIDTH; i++) { for (int j = 0; j < HEIGHT; j++) { equalized_image[i][j] = (int)(((float)cumulative_histogram[image[i][j]] / (WIDTH * HEIGHT)) * MAX_PIXEL_VALUE); } } // Output the original image printf("Original Image:\n"); for (int i = 0; i < WIDTH; i++) { for (int j = 0; j < HEIGHT; j++) { printf("%d ", image[i][j]); } printf("\n"); } // Output the equalized image printf("\nEqualized Image:\n"); for (int i = 0; i < WIDTH; i++) { for (int j = 0; j < HEIGHT; j++) { printf("%d ", equalized_image[i][j]); } printf("\n"); } } int main() { // Perform histogram equalization histogram_equalization(); return 0; } ``` ```bash terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-clang -march=rv32ima -mabi=ilp32 -o histogram.elf histogram.c --sysroot=/home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/riscv32-unknown-elf -L/home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/riscv32-unknown-elf/lib -lc -lgloss -lm terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-size histogram.elf text data bss dec hex filename 12646 380 56 13082 331a histogram.elf terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-readelf -h histogram.elf ELF Header: Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class: ELF32 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: EXEC (Executable file) Machine: RISC-V Version: 0x1 Entry point address: 0x10094 Start of program headers: 52 (bytes into file) Start of section headers: 263356 (bytes into file) Flags: 0x1, RVC, soft-float ABI Size of this header: 52 (bytes) Size of program headers: 32 (bytes) Number of program headers: 3 Size of section headers: 40 (bytes) Number of section headers: 24 Section header string table index: 23 ``` **running at qemu** ``` terry@ubuntu:~/qemu$ qemu-riscv32 ./histogram.elf Original Image: 120 50 200 30 80 90 180 60 40 140 70 20 110 10 160 130 100 150 190 220 30 80 120 50 200 Equalized Image: 163 71 244 40 112 122 214 81 51 183 91 20 142 10 204 173 132 193 224 255 40 112 163 71 244 ``` ```bash terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-clang -S -march=rv32ima -mabi=ilp32 -o histogram.S histogram.c ``` :::spoiler **assembly** ```assembly .text .attribute 4, 16 .attribute 5, "rv32i2p0_m2p0_a2p0" .file "histogram.c" .globl histogram_equalization # -- Begin function histogram_equalization .p2align 2 .type histogram_equalization,@function histogram_equalization: # @histogram_equalization # %bb.0: addi sp, sp, -2032 sw ra, 2028(sp) # 4-byte Folded Spill sw s0, 2024(sp) # 4-byte Folded Spill addi s0, sp, 2032 addi sp, sp, -176 addi a0, s0, -1036 mv a1, zero lui a2, 1048575 addi a2, a2, 1896 add a2, s0, a2 sw a1, 0(a2) # 4-byte Folded Spill addi a2, zero, 1024 call memset@plt # kill: def $x11 killed $x10 lui a0, 1048575 addi a0, a0, 1896 add a0, s0, a0 lw a0, 0(a0) # 4-byte Folded Reload sw a0, -1040(s0) j .LBB0_1 .LBB0_1: # =>This Loop Header: Depth=1 # Child Loop BB0_3 Depth 2 lw a1, -1040(s0) addi a0, zero, 4 blt a0, a1, .LBB0_8 j .LBB0_2 .LBB0_2: # in Loop: Header=BB0_1 Depth=1 mv a0, zero sw a0, -1044(s0) j .LBB0_3 .LBB0_3: # Parent Loop BB0_1 Depth=1 # => This Inner Loop Header: Depth=2 lw a1, -1044(s0) addi a0, zero, 4 blt a0, a1, .LBB0_6 j .LBB0_4 .LBB0_4: # in Loop: Header=BB0_3 Depth=2 lw a0, -1040(s0) addi a1, zero, 20 mul a0, a0, a1 lw a1, -1044(s0) slli a1, a1, 2 add a0, a0, a1 lui a1, %hi(image) addi a1, a1, %lo(image) add a0, a0, a1 lw a0, 0(a0) slli a1, a0, 2 addi a0, s0, -1036 add a1, a0, a1 lw a0, 0(a1) addi a0, a0, 1 sw a0, 0(a1) j .LBB0_5 .LBB0_5: # in Loop: Header=BB0_3 Depth=2 lw a0, -1044(s0) addi a0, a0, 1 sw a0, -1044(s0) j .LBB0_3 .LBB0_6: # in Loop: Header=BB0_1 Depth=1 j .LBB0_7 .LBB0_7: # in Loop: Header=BB0_1 Depth=1 lw a0, -1040(s0) addi a0, a0, 1 sw a0, -1040(s0) j .LBB0_1 .LBB0_8: lui a0, 1048575 addi a0, a0, 2028 add a0, s0, a0 mv a1, zero addi a2, zero, 1024 call memset@plt lw a0, -1036(s0) lui a1, 1048575 addi a1, a1, 2028 add a1, s0, a1 sw a0, 0(a1) addi a0, zero, 1 lui a1, 1048575 addi a1, a1, 2024 add a1, s0, a1 sw a0, 0(a1) j .LBB0_9 .LBB0_9: # =>This Inner Loop Header: Depth=1 lui a0, 1048575 addi a0, a0, 2024 add a0, s0, a0 lw a1, 0(a0) addi a0, zero, 255 blt a0, a1, .LBB0_12 j .LBB0_10 .LBB0_10: # in Loop: Header=BB0_9 Depth=1 lui a0, 1048575 addi a0, a0, 2024 add a0, s0, a0 lw a0, 0(a0) slli a3, a0, 2 lui a0, 1048575 addi a0, a0, 2028 add a0, s0, a0 add a1, a0, a3 lw a0, -4(a1) addi a2, s0, -1036 add a2, a2, a3 lw a2, 0(a2) add a0, a0, a2 sw a0, 0(a1) j .LBB0_11 .LBB0_11: # in Loop: Header=BB0_9 Depth=1 lui a0, 1048575 addi a0, a0, 2024 add a0, s0, a0 lw a0, 0(a0) addi a0, a0, 1 lui a1, 1048575 addi a1, a1, 2024 add a1, s0, a1 sw a0, 0(a1) j .LBB0_9 .LBB0_12: mv a0, zero lui a1, 1048575 addi a1, a1, 1920 add a1, s0, a1 sw a0, 0(a1) j .LBB0_13 .LBB0_13: # =>This Loop Header: Depth=1 # Child Loop BB0_15 Depth 2 lui a0, 1048575 addi a0, a0, 1920 add a0, s0, a0 lw a1, 0(a0) addi a0, zero, 4 blt a0, a1, .LBB0_20 j .LBB0_14 .LBB0_14: # in Loop: Header=BB0_13 Depth=1 mv a0, zero lui a1, 1048575 addi a1, a1, 1916 add a1, s0, a1 sw a0, 0(a1) j .LBB0_15 .LBB0_15: # Parent Loop BB0_13 Depth=1 # => This Inner Loop Header: Depth=2 lui a0, 1048575 addi a0, a0, 1916 add a0, s0, a0 lw a1, 0(a0) addi a0, zero, 4 blt a0, a1, .LBB0_18 j .LBB0_16 .LBB0_16: # in Loop: Header=BB0_15 Depth=2 lui a0, 1048575 addi a0, a0, 1920 add a0, s0, a0 lw a0, 0(a0) addi a1, zero, 20 mul a0, a0, a1 lui a1, 1048575 addi a1, a1, 1888 add a1, s0, a1 sw a0, 0(a1) # 4-byte Folded Spill lui a1, 1048575 addi a1, a1, 1916 add a1, s0, a1 lw a1, 0(a1) slli a1, a1, 2 lui a2, 1048575 addi a2, a2, 1892 add a2, s0, a2 sw a1, 0(a2) # 4-byte Folded Spill add a0, a0, a1 lui a1, %hi(image) addi a1, a1, %lo(image) add a0, a0, a1 lw a0, 0(a0) slli a1, a0, 2 lui a0, 1048575 addi a0, a0, 2028 add a0, s0, a0 add a0, a0, a1 lw a0, 0(a0) call __floatsisf@plt lui a1, 269440 call __divsf3@plt lui a1, 276464 call __mulsf3@plt call __fixsfsi@plt lui a1, 1048575 addi a1, a1, 1888 add a1, s0, a1 lw a3, 0(a1) # 4-byte Folded Reload lui a1, 1048575 addi a1, a1, 1892 add a1, s0, a1 lw a2, 0(a1) # 4-byte Folded Reload lui a1, 1048575 addi a1, a1, 1924 add a1, s0, a1 add a1, a1, a3 add a1, a1, a2 sw a0, 0(a1) j .LBB0_17 .LBB0_17: # in Loop: Header=BB0_15 Depth=2 lui a0, 1048575 addi a0, a0, 1916 add a0, s0, a0 lw a0, 0(a0) addi a0, a0, 1 lui a1, 1048575 addi a1, a1, 1916 add a1, s0, a1 sw a0, 0(a1) j .LBB0_15 .LBB0_18: # in Loop: Header=BB0_13 Depth=1 j .LBB0_19 .LBB0_19: # in Loop: Header=BB0_13 Depth=1 lui a0, 1048575 addi a0, a0, 1920 add a0, s0, a0 lw a0, 0(a0) addi a0, a0, 1 lui a1, 1048575 addi a1, a1, 1920 add a1, s0, a1 sw a0, 0(a1) j .LBB0_13 .LBB0_20: lui a0, %hi(.L.str) addi a0, a0, %lo(.L.str) call printf mv a0, zero lui a1, 1048575 addi a1, a1, 1912 add a1, s0, a1 sw a0, 0(a1) j .LBB0_21 .LBB0_21: # =>This Loop Header: Depth=1 # Child Loop BB0_23 Depth 2 lui a0, 1048575 addi a0, a0, 1912 add a0, s0, a0 lw a1, 0(a0) addi a0, zero, 4 blt a0, a1, .LBB0_28 j .LBB0_22 .LBB0_22: # in Loop: Header=BB0_21 Depth=1 mv a0, zero lui a1, 1048575 addi a1, a1, 1908 add a1, s0, a1 sw a0, 0(a1) j .LBB0_23 .LBB0_23: # Parent Loop BB0_21 Depth=1 # => This Inner Loop Header: Depth=2 lui a0, 1048575 addi a0, a0, 1908 add a0, s0, a0 lw a1, 0(a0) addi a0, zero, 4 blt a0, a1, .LBB0_26 j .LBB0_24 .LBB0_24: # in Loop: Header=BB0_23 Depth=2 lui a0, 1048575 addi a0, a0, 1912 add a0, s0, a0 lw a0, 0(a0) addi a1, zero, 20 mul a0, a0, a1 lui a1, 1048575 addi a1, a1, 1908 add a1, s0, a1 lw a1, 0(a1) slli a1, a1, 2 add a0, a0, a1 lui a1, %hi(image) addi a1, a1, %lo(image) add a0, a0, a1 lw a1, 0(a0) lui a0, %hi(.L.str.1) addi a0, a0, %lo(.L.str.1) call printf j .LBB0_25 .LBB0_25: # in Loop: Header=BB0_23 Depth=2 lui a0, 1048575 addi a0, a0, 1908 add a0, s0, a0 lw a0, 0(a0) addi a0, a0, 1 lui a1, 1048575 addi a1, a1, 1908 add a1, s0, a1 sw a0, 0(a1) j .LBB0_23 .LBB0_26: # in Loop: Header=BB0_21 Depth=1 lui a0, %hi(.L.str.2) addi a0, a0, %lo(.L.str.2) call printf j .LBB0_27 .LBB0_27: # in Loop: Header=BB0_21 Depth=1 lui a0, 1048575 addi a0, a0, 1912 add a0, s0, a0 lw a0, 0(a0) addi a0, a0, 1 lui a1, 1048575 addi a1, a1, 1912 add a1, s0, a1 sw a0, 0(a1) j .LBB0_21 .LBB0_28: lui a0, %hi(.L.str.3) addi a0, a0, %lo(.L.str.3) call printf mv a0, zero lui a1, 1048575 addi a1, a1, 1904 add a1, s0, a1 sw a0, 0(a1) j .LBB0_29 .LBB0_29: # =>This Loop Header: Depth=1 # Child Loop BB0_31 Depth 2 lui a0, 1048575 addi a0, a0, 1904 add a0, s0, a0 lw a1, 0(a0) addi a0, zero, 4 blt a0, a1, .LBB0_36 j .LBB0_30 .LBB0_30: # in Loop: Header=BB0_29 Depth=1 mv a0, zero lui a1, 1048575 addi a1, a1, 1900 add a1, s0, a1 sw a0, 0(a1) j .LBB0_31 .LBB0_31: # Parent Loop BB0_29 Depth=1 # => This Inner Loop Header: Depth=2 lui a0, 1048575 addi a0, a0, 1900 add a0, s0, a0 lw a1, 0(a0) addi a0, zero, 4 blt a0, a1, .LBB0_34 j .LBB0_32 .LBB0_32: # in Loop: Header=BB0_31 Depth=2 lui a0, 1048575 addi a0, a0, 1904 add a0, s0, a0 lw a0, 0(a0) addi a1, zero, 20 mul a1, a0, a1 lui a0, 1048575 addi a0, a0, 1924 add a0, s0, a0 add a0, a0, a1 lui a1, 1048575 addi a1, a1, 1900 add a1, s0, a1 lw a1, 0(a1) slli a1, a1, 2 add a0, a0, a1 lw a1, 0(a0) lui a0, %hi(.L.str.1) addi a0, a0, %lo(.L.str.1) call printf j .LBB0_33 .LBB0_33: # in Loop: Header=BB0_31 Depth=2 lui a0, 1048575 addi a0, a0, 1900 add a0, s0, a0 lw a0, 0(a0) addi a0, a0, 1 lui a1, 1048575 addi a1, a1, 1900 add a1, s0, a1 sw a0, 0(a1) j .LBB0_31 .LBB0_34: # in Loop: Header=BB0_29 Depth=1 lui a0, %hi(.L.str.2) addi a0, a0, %lo(.L.str.2) call printf j .LBB0_35 .LBB0_35: # in Loop: Header=BB0_29 Depth=1 lui a0, 1048575 addi a0, a0, 1904 add a0, s0, a0 lw a0, 0(a0) addi a0, a0, 1 lui a1, 1048575 addi a1, a1, 1904 add a1, s0, a1 sw a0, 0(a1) j .LBB0_29 .LBB0_36: addi sp, sp, 176 lw s0, 2024(sp) # 4-byte Folded Reload lw ra, 2028(sp) # 4-byte Folded Reload addi sp, sp, 2032 ret .Lfunc_end0: .size histogram_equalization, .Lfunc_end0-histogram_equalization # -- End function .globl main # -- Begin function main .p2align 2 .type main,@function main: # @main # %bb.0: addi sp, sp, -16 sw ra, 12(sp) # 4-byte Folded Spill sw s0, 8(sp) # 4-byte Folded Spill addi s0, sp, 16 mv a0, zero sw a0, -16(s0) # 4-byte Folded Spill sw a0, -12(s0) call histogram_equalization lw a0, -16(s0) # 4-byte Folded Reload lw s0, 8(sp) # 4-byte Folded Reload lw ra, 12(sp) # 4-byte Folded Reload addi sp, sp, 16 ret .Lfunc_end1: .size main, .Lfunc_end1-main # -- End function .type image,@object # @image .data .globl image .p2align 2 image: .word 120 # 0x78 .word 50 # 0x32 .word 200 # 0xc8 .word 30 # 0x1e .word 80 # 0x50 .word 90 # 0x5a .word 180 # 0xb4 .word 60 # 0x3c .word 40 # 0x28 .word 140 # 0x8c .word 70 # 0x46 .word 20 # 0x14 .word 110 # 0x6e .word 10 # 0xa .word 160 # 0xa0 .word 130 # 0x82 .word 100 # 0x64 .word 150 # 0x96 .word 190 # 0xbe .word 220 # 0xdc .word 30 # 0x1e .word 80 # 0x50 .word 120 # 0x78 .word 50 # 0x32 .word 200 # 0xc8 .size image, 100 .type .L.str,@object # @.str .section .rodata.str1.1,"aMS",@progbits,1 .L.str: .asciz "Original Image:\n" .size .L.str, 17 .type .L.str.1,@object # @.str.1 .L.str.1: .asciz "%d " .size .L.str.1, 4 .type .L.str.2,@object # @.str.2 .L.str.2: .asciz "\n" .size .L.str.2, 2 .type .L.str.3,@object # @.str.3 .L.str.3: .asciz "\nEqualized Image:\n" .size .L.str.3, 19 .ident "riscv32-embecosm-clang-ubuntu1804-20210509 clang version 13.0.0 (https://mirrors.git.embecosm.com/mirrors/llvm-project.git 4aec8f4ce0f564aa68c23b9e29c2e3a945eec947)" .section ".note.GNU-stack","",@progbits .addrsig .addrsig_sym histogram_equalization .addrsig_sym printf .addrsig_sym image ``` ::: # Problem Analyze: ```bash terry@ubuntu:~/qemu$ ./configure --target-list=riscv64-softmmu --prefix=$RISCV/qemu ERROR: "cc" either does not exist or does not work ========================== sudo apt-get update sudo apt-get install build-essential ========================== ``` didn't find the header file ```bash terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-clang -march=rv32ima -mabi=ilp32 -o sobel.elf sobel.c sobel.c:1:10: fatal error: 'stdio.h' file not found #include <stdio.h> ^~~~~~~~~ 1 error generated. ==================== export C_INCLUDE_PATH=~/project/gcc/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/riscv32-unknown-elf/include ==================== ``` need to find the crt0.o, libc.a Path ```bash terry@ubuntu:~/project$ ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-clang -march=rv32ima -mabi=ilp32 -o sobel.elf sobel.c /home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-ld: cannot find crt0.o: No such file or directory /home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-ld: cannot find -lc /home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-ld: cannot find -lgloss clang-13: error: ld command failed with exit code 1 (use -v to see invocation) ======================= export LIBRARY_PATH=~/project/gcc/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/riscv32-unknown-elf/lib export LDFLAGS="-L/home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/riscv32-unknown-elf/lib -lc -lgloss" ~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/bin/riscv32-unknown-elf-clang -march=rv32ima -mabi=ilp32 -o sobel.elf sobel.c \ --sysroot=/home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/riscv32-unknown-elf \ -L/home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/riscv32-unknown-elf/lib \ -lc -lgloss -lm ======================= ``` ```bash CC hw/display/edid-generate.o CC scsi/qemu-pr-helper.o make: *** No rule to make target 'riscv64-softmmu/config-devices.mak', needed by 'config-all-devices.mak'. Stop. make: *** Waiting for unfinished jobs.... CC qemu-bridge-helper.o ===================== ./configure --target-list=riscv64-softmmu --prefix=$RISCV/qemu make -j $(nproc) ===================== ``` Remote branch ```bash terry@ubuntu:~/project/qemu$ git clone --branch rvv-1.0-upstream-v7-fix https://github.com/sifive/qemu.git Cloning into 'qemu'... fatal: Remote branch rvv-1.0-upstream-v7-fix not found in upstream origin ================= git ls-remote --heads https://github.com/sifive/qemu.git ================= ``` fatal error: cannot execute 'cc1' ```bash terry@ubuntu:~/project$ CROSS_COMPILE=riscv64-unknown-linux-gnu- make install riscv64-unknown-linux-gnu-gcc: fatal error: cannot execute 'cc1': execvp: No such file or directory compilation terminated. CC applets/applets.o riscv64-unknown-linux-gnu-gcc: fatal error: cannot execute 'cc1': execvp: No such file or directory compilation terminated. make[1]: *** [scripts/Makefile.build:198: applets/applets.o] Error 1 make: *** [Makefile:372: applets_dir] Error 2 ``` I found this page and try to ckeck my toolchain path https://stackoverflow.com/questions/56810443/gcc-without-full-path-error-trying-to-exec-cc1-execvp-no-such-file-or-direc this instruction let my therminal window get closed, so I can't show result ```bash terry@ubuntu:~/project$ qemu-system-riscv32 -nographic -kernel ./sobel.elf ``` and I try again , Finally can be executed ```bash sudo ./configure --target-list=riscv32-linux-user --prefix=$RISCV/qemu sudo apt install qemu-user ================== terry@ubuntu:~/qemu$ qemu-riscv32 ./hello.elf Hello World ================== ``` # Environment Variables ```bash export PATH=/home/terry/riscv-gnu-toolchain/build-gcc-newlib-stage1/gcc/:$PATH export PATH=~/project/llvm-clang/bin:$PATH export PATH=~/project/gcc/bin:$PATH export PATH=~/qemu/build:$PATH export PATH="/qemu/bin:$PATH" export PATH=$PATH:/opt/riscv32/bin export PATH=/project/gc/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/bin:$PATH export PATH=~/project/gcc/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/bin:$PATH export LIBRARY_PATH=~/project/gcc/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/riscv32-unknown-elf/lib export C_INCLUDE_PATH=~/project/gcc/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/riscv32-unknown-elf/include export LIBRARY_PATH=~/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/lib/rv32:$LIBRARY_PATH export LIBRARY_PATH=~/project/gcc/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/riscv32-unknown-elf/lib:$LIBRARY_PATH export LIBRARY_PATH=~/project/gcc/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/riscv32-unknown-elf/lib/rv32imafc/ilp32f:$LIBRARY_PATH export PATH=~/project/gcc/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/bin:$PATH export LIBRARY_PATH=~/project/gcc/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/riscv32-unknown-elf/lib/rv32imafc/ilp32f:$LIBRARY_PATH export PATH=~/project/gcc/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/bin:$PATH export LIBRARY_PATH=/home/terry/project/gcc/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/riscv32-unknown-elf/lib/rv32im/ilp32/crt0.o:$LIBRARY_PATH export LIBRARY_PATH=/home/terry/project/gcc/riscv32-embecosm-gcc-ubuntu1804-20210523-defaultnewlib/riscv32-unknown-elf/lib/crt0.o:$LIBRARY_PATH export LIBRARY_PATH=/home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/riscv32-unknown-elf/lib/crt0.o:$LIBRARY_PATH export LDFLAGS="-L/home/terry/project/llvm-clang/riscv32-embecosm-clang-ubuntu1804-20210509/riscv32-unknown-elf/lib -lc -lgloss" ``` I want to try use qemu-system-riscv32 execution .elf on QEMU,but I didn't findout how to print the result at this UI ![image](https://hackmd.io/_uploads/BkEoaYzYa.png) And I trying to find which instruction can i use ![image](https://hackmd.io/_uploads/BJNqZtGY6.png) ``` terry@ubuntu:~/qemu/linux-user/riscv$ ls cpu_loop.c sockbits.h syscall64_nr.h target_cpu.h target_fcntl.h target_structs.h termbits.h signal.c syscall32_nr.h syscall_nr.h target_elf.h target_signal.h target_syscall.h ``` ref : https://lists.riscv.org/g/tech-vector-ext/topic/85564316?p=,,,20,0,0,0::recentpostdate/sticky,,,20,2,0,85564316 :::danger Not working. ::: # **Reference** https://risc-v-getting-started-guide.readthedocs.io/en/latest/linux-qemu.html https://lists.riscv.org/g/tech-vector-ext/topic/85564316?p=,,,20,0,0,0::recentpostdate/sticky,,,20,2,0,85564316 https://jasonblog.github.io/note/qemu/yong_qemu_mo_ni_arm.html https://github.com/johnwinans/riscv-toolchain-install-guide/blob/main/README.md https://www.youtube.com/watch?v=iWQRV-KJ7tQ https://hackmd.io/@nx1bTzFpQvaKD_yxYRmBaQ/S1l4siGA_ https://blog.csdn.net/sucaiwa/article/details/129293493 https://github.com/sifive/freedom-tools/releases https://medium.com/swark/%E5%9C%A8qemu%E4%B8%8A%E5%9F%B7%E8%A1%8C64-bit-risc-v-linux-2a527a078819 https://packages.ubuntu.com/search?keywords=gcc-riscv64-linux-gnu https://github.com/sifive/qemu/tree/rvv-zve32f-zve64f-upstream-v2 https://github.com/riscv-collab/riscv-gcc/issues/374 https://github.com/riscv-collab/riscv-gcc/issues/374 https://medium.com/swark/%E5%9C%A8qemu%E4%B8%8A%E5%9F%B7%E8%A1%8C64-bit-risc-v-linux-2a527a078819