From 6d742bf869fb0d62fe145406fd1feff135f85507 Mon Sep 17 00:00:00 2001 From: Samir Rashid Date: Thu, 20 Mar 2025 14:37:57 -0700 Subject: [PATCH 1/4] test: prepare cross compile automation --- .gitignore | 2 ++ run.sh | 9 ++++---- tests/add/test_add.rs | 4 +++- tests/binaries/flake.nix | 1 + tests/binaries/hello_world.c | 2 +- tests/binaries/riscv/cross.nix | 9 ++++++++ tests/binaries/riscv/flake.nix | 1 + tests/binaries/riscv/shell.nix | 27 +++++++++++++++++++++++ tests/print/print.riscv.s | 40 ++++++++++++++++++++++++++++++++++ 9 files changed, 89 insertions(+), 6 deletions(-) create mode 100644 tests/binaries/riscv/cross.nix create mode 100644 tests/binaries/riscv/shell.nix create mode 100644 tests/print/print.riscv.s diff --git a/.gitignore b/.gitignore index 161d7f2..c6ffd5f 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,8 @@ Cargo.lock # temporary files *.bin +*.as +a.out .vscode/ test_binary_translate* \ No newline at end of file diff --git a/run.sh b/run.sh index 31240d2..e2141ff 100755 --- a/run.sh +++ b/run.sh @@ -3,7 +3,8 @@ ASM_FILE=$1 PLATFORM="" LD_FLAGS="" -BENCHMARKING="false" # "true" to enable +BENCHMARKING="true" # "true" to enable +QEMU="qemu-riscv64" if [[ -z "$ASM_FILE" ]]; then echo "Error: Assembly (.S) file is not passed in." @@ -12,7 +13,7 @@ if [[ -z "$ASM_FILE" ]]; then fi if [[ "$OSTYPE" == "linux-gnu"* ]]; then - PLATFORM="aarch64-linux-gnu" + PLATFORM="riscv64-unknown-linux-gnu-" fi if [[ "$OSTYPE" == "darwin"* ]]; then @@ -23,9 +24,9 @@ fi "$PLATFORM"as "$ASM_FILE" -o "$ASM_FILE".as || { echo "Assembly compilation failed"; exit 1; } "$PLATFORM"ld "$ASM_FILE".as -o "$ASM_FILE".bin $LD_FLAGS || { echo "Linking failed"; exit 1; } -./"$ASM_FILE".bin +"$QEMU" ./"$ASM_FILE".bin echo "$?" if [ "$BENCHMARKING" = true ]; then - hyperfine -r 1000 -w 100 -Ni ./"$ASM_FILE".bin + hyperfine -r 1000 -w 100 -Ni ""$QEMU" ./"$ASM_FILE".bin" fi diff --git a/tests/add/test_add.rs b/tests/add/test_add.rs index a2686d3..47b53e9 100644 --- a/tests/add/test_add.rs +++ b/tests/add/test_add.rs @@ -9,7 +9,9 @@ mod tests { #[test] fn test_binary_translate() { let riscv_asm: Vec = vec![ - RiscVInstruction::Verbatim { text: START.to_string() }, + RiscVInstruction::Verbatim { + text: START.to_string(), + }, RiscVInstruction::Addi { dest: RiscVRegister::SP, src: RiscVRegister::SP, diff --git a/tests/binaries/flake.nix b/tests/binaries/flake.nix index d408be5..bad4d02 100644 --- a/tests/binaries/flake.nix +++ b/tests/binaries/flake.nix @@ -19,6 +19,7 @@ # Use the same mkShell as documented above packages = with pkgs; [ gcc +# qemu # pkgs.clang-tools ]; }; diff --git a/tests/binaries/hello_world.c b/tests/binaries/hello_world.c index 13f3050..5a62c9d 100644 --- a/tests/binaries/hello_world.c +++ b/tests/binaries/hello_world.c @@ -1,4 +1,4 @@ -#import +#include int main(void) { printf("hello world\n"); diff --git a/tests/binaries/riscv/cross.nix b/tests/binaries/riscv/cross.nix new file mode 100644 index 0000000..2cef3a8 --- /dev/null +++ b/tests/binaries/riscv/cross.nix @@ -0,0 +1,9 @@ +with import { + crossSystem = { + config = "riscv64-unknown-linux-gnu"; + }; +}; + +mkShell { + buildInputs = [ ]; # your dependencies here +} diff --git a/tests/binaries/riscv/flake.nix b/tests/binaries/riscv/flake.nix index 3a391c7..d252266 100644 --- a/tests/binaries/riscv/flake.nix +++ b/tests/binaries/riscv/flake.nix @@ -19,6 +19,7 @@ # Use the same mkShell as documented above packages = with pkgs; [ gcc + # qemu # pkgs.clang-tools ]; }; diff --git a/tests/binaries/riscv/shell.nix b/tests/binaries/riscv/shell.nix new file mode 100644 index 0000000..2e5a6f6 --- /dev/null +++ b/tests/binaries/riscv/shell.nix @@ -0,0 +1,27 @@ +let + pkgs = import + { + crossSystem = (import ).systems.examples.riscv64; + }; +in +pkgs.mkShell { + name = "kernel-qemu"; + depsBuildBuild = with pkgs; [ + # Kernel + gcc + # gnumake + # flex + # bison + # bc + # ncurses + # pkg-config + # perl + # # Modules + # kmod + # # ramfs + # cpio + # #justqemuthings + # qemu + ]; +} + diff --git a/tests/print/print.riscv.s b/tests/print/print.riscv.s new file mode 100644 index 0000000..3c3179d --- /dev/null +++ b/tests/print/print.riscv.s @@ -0,0 +1,40 @@ +buf: + .string "Hello world!" + +.section .text +.globl _start + +_start: + # while i < 1000 + li a3, 1000 +.loop: + addi a3, a3, -1 + ble a3, x0, .end + + + # write(stdout, buf, len) + + # syscall number + li a7,64 + # arg 2 + li a2,13 + # arg 1 + lui a0,%hi(buf) + addi a1,a0,%lo(buf) + # arg 0 + li a0,1 + # syscall + ecall + j .loop + +.end: + # exit(0) + + # syscall number + li a7,93 + # arg 0 + li a0,0 + # syscall + ecall + + From 56d1f6b5422d9cf6a50c42b132e0d1a2af5d97c2 Mon Sep 17 00:00:00 2001 From: Samir Rashid Date: Thu, 20 Mar 2025 23:04:23 -0700 Subject: [PATCH 2/4] build: finally fix cross compile --- tests/binaries/riscv/cross.arm.nix | 9 +++++++++ tests/binaries/riscv/flake.lock | 27 --------------------------- tests/binaries/riscv/flake.nix | 27 --------------------------- tests/binaries/riscv/shell.nix | 27 --------------------------- 4 files changed, 9 insertions(+), 81 deletions(-) create mode 100644 tests/binaries/riscv/cross.arm.nix delete mode 100644 tests/binaries/riscv/flake.lock delete mode 100644 tests/binaries/riscv/flake.nix delete mode 100644 tests/binaries/riscv/shell.nix diff --git a/tests/binaries/riscv/cross.arm.nix b/tests/binaries/riscv/cross.arm.nix new file mode 100644 index 0000000..4ea8dd7 --- /dev/null +++ b/tests/binaries/riscv/cross.arm.nix @@ -0,0 +1,9 @@ +with import { + crossSystem = { + config = "aarch64-unknown-linux-gnu"; + }; +}; + +mkShell { + buildInputs = [ ]; # your dependencies here +} diff --git a/tests/binaries/riscv/flake.lock b/tests/binaries/riscv/flake.lock deleted file mode 100644 index eeec239..0000000 --- a/tests/binaries/riscv/flake.lock +++ /dev/null @@ -1,27 +0,0 @@ -{ - "nodes": { - "nixpkgs": { - "locked": { - "lastModified": 1741600792, - "narHash": "sha256-yfDy6chHcM7pXpMF4wycuuV+ILSTG486Z/vLx/Bdi6Y=", - "owner": "nixos", - "repo": "nixpkgs", - "rev": "ebe2788eafd539477f83775ef93c3c7e244421d3", - "type": "github" - }, - "original": { - "owner": "nixos", - "ref": "nixos-24.11", - "repo": "nixpkgs", - "type": "github" - } - }, - "root": { - "inputs": { - "nixpkgs": "nixpkgs" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/tests/binaries/riscv/flake.nix b/tests/binaries/riscv/flake.nix deleted file mode 100644 index d252266..0000000 --- a/tests/binaries/riscv/flake.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ - description = "A very basic flake"; - - inputs = { - nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; - }; - - - outputs = { self, nixpkgs }: - let - pkgs = import nixpkgs { - # inherit system; - system = "x86_64-linux"; - crossSystem.config = "riscv64-linux-gnu"; - }; - in - { - devShells.x86_64-linux.default = pkgs.mkShell { - # Use the same mkShell as documented above - packages = with pkgs; [ - gcc - # qemu - # pkgs.clang-tools - ]; - }; - }; -} diff --git a/tests/binaries/riscv/shell.nix b/tests/binaries/riscv/shell.nix deleted file mode 100644 index 2e5a6f6..0000000 --- a/tests/binaries/riscv/shell.nix +++ /dev/null @@ -1,27 +0,0 @@ -let - pkgs = import - { - crossSystem = (import ).systems.examples.riscv64; - }; -in -pkgs.mkShell { - name = "kernel-qemu"; - depsBuildBuild = with pkgs; [ - # Kernel - gcc - # gnumake - # flex - # bison - # bc - # ncurses - # pkg-config - # perl - # # Modules - # kmod - # # ramfs - # cpio - # #justqemuthings - # qemu - ]; -} - From ee0e785e229ad99f2c647438c57cd6cf1aa0d7cf Mon Sep 17 00:00:00 2001 From: Samir Rashid Date: Thu, 20 Mar 2025 23:05:53 -0700 Subject: [PATCH 3/4] test: run add and print thousands of times To support better benchmarking, loop the `main` function thousands of times. --- src/utils.rs | 63 ++++++++++++++++++++++++++++++++++++++- tests/add/add.arm.s | 13 ++++++++ tests/add/add.riscv.s | 22 ++++++++++++++ tests/add/test_add.rs | 4 +-- tests/echo/test_echo.rs | 4 +-- tests/print/print.arm.s | 14 +++++++-- tests/print/print.riscv.s | 2 +- tests/print/test_print.rs | 45 ++++++++++++++++++++++++---- tests/test_translation.rs | 6 ++-- 9 files changed, 155 insertions(+), 18 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index eb35249..d621b4b 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -2,7 +2,68 @@ use std::fs; use crate::{instruction::RiscVInstruction, translate::translate_instrs}; -pub const START: &str = r#" +/// Loop main() 10,000 times. Uses a3. +pub const RISCV_LOOP_START: &str = r#" +.text + +.global _start +.global _main + +.balign 4 # not sure if these are needed for RISC-V +_start: + # while i < 10,000 + li a3, 10000 +.loop: + addi a3, a3, -1 + ble a3, x0, .end + + # main() + jal ra, main + + # while loop + j .loop +.end: + # exit(0) + li a7,93 + ecall + +.balign 4 +_main: +main: +"#; + +/// Loop main() 10,000 times. Uses x3 +pub const ARM_LOOP_START: &str = r#" +.text + +.global _start +.global _main + +.balign 4 +_start: +# i = 10,000 +mov x3, #10000 +# while i > 0 +.loop: +sub x3, x3, 1 + +cmp x3, xzr +ble .end + +# main() +bl main + +b .loop +.end: +mov x8, #93 +svc #0 + +.balign 4 +_main: +main: +"#; + +pub const ARM_START: &str = r#" .text .global _start diff --git a/tests/add/add.arm.s b/tests/add/add.arm.s index 391c523..ab59d06 100644 --- a/tests/add/add.arm.s +++ b/tests/add/add.arm.s @@ -6,7 +6,20 @@ .balign 4 _start: +# i = 10,000 +mov x3, #10000 +# while i > 0 +.loop: +sub x3, x3, 1 + +cmp x3, xzr +ble .end + +# main() bl main + +b .loop +.end: mov x8, #93 svc #0 diff --git a/tests/add/add.riscv.s b/tests/add/add.riscv.s index 309ad1e..8d229ac 100644 --- a/tests/add/add.riscv.s +++ b/tests/add/add.riscv.s @@ -1,3 +1,25 @@ +.text + +.global _start +.global _main + +.balign 4 # not sure if these are needed for RISC-V +_start: + # while i < 10,000 + li a3, 10000 +.loop: + addi a3, a3, -1 + ble a3, x0, .end + + # main() + jal ra, main + + # while loop + j .loop +.end: + # exit(0) + li a7,93 + ecall main: addi sp,sp,-32 sd ra,24(sp) diff --git a/tests/add/test_add.rs b/tests/add/test_add.rs index 47b53e9..1696077 100644 --- a/tests/add/test_add.rs +++ b/tests/add/test_add.rs @@ -4,13 +4,13 @@ mod tests { use binary_room::translate::*; use binary_room::utils; use binary_room::utils::translate_to_file; - use binary_room::utils::START; + use binary_room::utils::ARM_LOOP_START; #[test] fn test_binary_translate() { let riscv_asm: Vec = vec![ RiscVInstruction::Verbatim { - text: START.to_string(), + text: ARM_LOOP_START.to_string(), }, RiscVInstruction::Addi { dest: RiscVRegister::SP, diff --git a/tests/echo/test_echo.rs b/tests/echo/test_echo.rs index 36cd6f5..a3e8c92 100644 --- a/tests/echo/test_echo.rs +++ b/tests/echo/test_echo.rs @@ -4,7 +4,7 @@ mod tests { use binary_room::translate::*; use binary_room::utils; use binary_room::utils::translate_to_file; - use binary_room::utils::START; + use binary_room::utils::ARM_START; const buf: &str = r#" .buf: @@ -16,7 +16,7 @@ mod tests { let riscv_asm: Vec = vec![ // RiscVInstruction::Verbatim { text: buf.to_string() }, RiscVInstruction::Verbatim { - text: START.to_string(), + text: ARM_START.to_string(), }, // read syscall RiscVInstruction::Addi { diff --git a/tests/print/print.arm.s b/tests/print/print.arm.s index 392f418..9b48c8a 100644 --- a/tests/print/print.arm.s +++ b/tests/print/print.arm.s @@ -1,5 +1,5 @@ -.buf: +buf: .string "hello world\n" @@ -18,11 +18,19 @@ svc #0 _main: main: +mov x3, 1000 +.loop: +sub x3, x3, 1 +cmp x3, xzr +ble .end mov x8, 64 mov x2, 14 -adrp x0, .buf -add x1, x0, :lo12:.buf +adrp x0, buf +add x1, x0, :lo12:buf mov x0, 1 svc 0 +b .loop +.end: mov x8, 93 +mov x0, 0 svc 0 diff --git a/tests/print/print.riscv.s b/tests/print/print.riscv.s index 3c3179d..66cdfc8 100644 --- a/tests/print/print.riscv.s +++ b/tests/print/print.riscv.s @@ -1,5 +1,5 @@ buf: - .string "Hello world!" + .string "Hello world!\n" .section .text .globl _start diff --git a/tests/print/test_print.rs b/tests/print/test_print.rs index 8471e92..bb428c1 100644 --- a/tests/print/test_print.rs +++ b/tests/print/test_print.rs @@ -4,10 +4,10 @@ mod tests { use binary_room::translate::*; use binary_room::utils; use binary_room::utils::translate_to_file; - use binary_room::utils::START; + use binary_room::utils::ARM_START; const buf: &str = r#" -.buf: +buf: .string "hello world\n" "#; @@ -18,7 +18,28 @@ mod tests { text: buf.to_string(), }, RiscVInstruction::Verbatim { - text: START.to_string(), + text: ARM_START.to_string(), + }, + // While i < 1000 + RiscVInstruction::Li { + dest: RiscVRegister::A3, + imm: 1000, + }, + RiscVInstruction::Label { + name: ".loop".to_string(), + }, + RiscVInstruction::Addi { + dest: RiscVRegister::A3, + src: RiscVRegister::A3, + imm: -1, + }, + RiscVInstruction::Ble { + arg1: RiscVRegister::A3, + arg2: RiscVRegister::X0, + target: RiscVVal::LabelOffset { + label: ".end".to_string(), + offset: 0, + }, }, // write syscall RiscVInstruction::Li { @@ -32,7 +53,7 @@ mod tests { RiscVInstruction::Lui { dest: RiscVRegister::A0, src: RiscVVal::LabelOffset { - label: ".buf".to_string(), + label: "buf".to_string(), offset: 9998, }, }, @@ -40,7 +61,7 @@ mod tests { dest: RiscVRegister::A1, src: RiscVRegister::A0, label: RiscVVal::LabelOffset { - label: ".buf".to_string(), + label: "buf".to_string(), offset: 9999, }, }, @@ -49,12 +70,24 @@ mod tests { imm: 1, }, RiscVInstruction::ECall, + RiscVInstruction::J { + target: RiscVVal::LabelOffset { + label: ".loop".to_string(), + offset: 0, + }, + }, + RiscVInstruction::Label { + name: ".end".to_string(), + }, // exit syscall RiscVInstruction::Li { dest: RiscVRegister::A7, imm: 93, }, - // RiscVInstruction::Li { dest: RiscVRegister::A0, imm: 0 }, + RiscVInstruction::Li { + dest: RiscVRegister::A0, + imm: 0, + }, RiscVInstruction::ECall, ]; diff --git a/tests/test_translation.rs b/tests/test_translation.rs index dfc4251..34241d9 100644 --- a/tests/test_translation.rs +++ b/tests/test_translation.rs @@ -4,13 +4,13 @@ mod tests { use binary_room::translate::*; use binary_room::utils; use binary_room::utils::translate_to_file; - use binary_room::utils::START; + use binary_room::utils::ARM_START; #[test] fn test_binary_translate() { let riscv_asm: Vec = vec![ RiscVInstruction::Verbatim { - text: START.to_string(), + text: ARM_START.to_string(), }, RiscVInstruction::Addi { dest: RiscVRegister::SP, @@ -242,7 +242,7 @@ mod tests { fn test_loop() { let riscv_asm: Vec = vec![ RiscVInstruction::Verbatim { - text: START.to_string(), + text: ARM_START.to_string(), }, RiscVInstruction::Addi { dest: RiscVRegister::SP, From 1127f55f1ad03dd19094c0c9d9bc87f5ed3cfeba Mon Sep 17 00:00:00 2001 From: Samir Rashid Date: Thu, 20 Mar 2025 23:08:41 -0700 Subject: [PATCH 4/4] test: improve benchmarking different architectures, remove arm asms --- .gitignore | 1 + run.sh | 30 ++++++++++++++++++++------ tests/add/add.arm.s | 47 ----------------------------------------- tests/echo/echo.arm.s | 29 ------------------------- tests/print/print.arm.s | 36 ------------------------------- 5 files changed, 24 insertions(+), 119 deletions(-) delete mode 100644 tests/add/add.arm.s delete mode 100644 tests/echo/echo.arm.s delete mode 100644 tests/print/print.arm.s diff --git a/.gitignore b/.gitignore index c6ffd5f..36fa30f 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,7 @@ Cargo.lock # temporary files *.bin +*.arm.s *.as a.out diff --git a/run.sh b/run.sh index e2141ff..10e1bea 100755 --- a/run.sh +++ b/run.sh @@ -1,19 +1,34 @@ #!/usr/bin/env bash -ASM_FILE=$1 +ARCH=$1 +ASM_FILE=$2 PLATFORM="" LD_FLAGS="" BENCHMARKING="true" # "true" to enable -QEMU="qemu-riscv64" +QEMU="" -if [[ -z "$ASM_FILE" ]]; then - echo "Error: Assembly (.S) file is not passed in." - echo "Usage: ./run.sh test_binary_translate_add.S" +if [[ -z "$ARCH" || -z "$ASM_FILE" ]]; then + echo "Error: Architecture and assembly (.S) file must be provided." + echo "Usage: ./run.sh [riscv|arm] " exit 1 fi -if [[ "$OSTYPE" == "linux-gnu"* ]]; then - PLATFORM="riscv64-unknown-linux-gnu-" +if [[ "$ARCH" != "riscv" && "$ARCH" != "arm" ]]; then + echo "Error: Architecture must be either 'riscv' or 'arm'." + echo "Usage: ./run.sh [riscv|arm] " + exit 1 +fi + +if [[ "$ARCH" == "riscv" ]]; then + QEMU="qemu-riscv64" + if [[ "$OSTYPE" == "linux-gnu"* ]]; then + PLATFORM="riscv64-unknown-linux-gnu-" + fi +elif [[ "$ARCH" == "arm" ]]; then + QEMU="qemu-aarch64" + if [[ "$OSTYPE" == "linux-gnu"* ]]; then + PLATFORM="aarch64-unknown-linux-gnu-" + fi fi if [[ "$OSTYPE" == "darwin"* ]]; then @@ -30,3 +45,4 @@ echo "$?" if [ "$BENCHMARKING" = true ]; then hyperfine -r 1000 -w 100 -Ni ""$QEMU" ./"$ASM_FILE".bin" fi + diff --git a/tests/add/add.arm.s b/tests/add/add.arm.s deleted file mode 100644 index ab59d06..0000000 --- a/tests/add/add.arm.s +++ /dev/null @@ -1,47 +0,0 @@ - -.text - -.global _start -.global _main - -.balign 4 -_start: -# i = 10,000 -mov x3, #10000 -# while i > 0 -.loop: -sub x3, x3, 1 - -cmp x3, xzr -ble .end - -# main() -bl main - -b .loop -.end: -mov x8, #93 -svc #0 - -.balign 4 -_main: -main: - -sub sp, sp, 32 -str lr, [sp, 24] -str x29, [sp, 16] -add x29, sp, 32 -mov x5, 3 -str w5, [x29, -20] -mov x5, 4 -str w5, [x29, -24] -ldr w5, [x29, -20] -add x4, x5, 0 -ldr w5, [x29, -24] -add w5, w4, w5 -sxtw x5, w5 -add x0, x5, 0 -ldr lr, [sp, 24] -ldr x29, [sp, 16] -add sp, sp, 32 -blr lr diff --git a/tests/echo/echo.arm.s b/tests/echo/echo.arm.s deleted file mode 100644 index 44c8b7a..0000000 --- a/tests/echo/echo.arm.s +++ /dev/null @@ -1,29 +0,0 @@ - -.text - -.global _start -.global _main - -.balign 4 -_start: -bl main -mov x8, #93 -svc #0 - -.balign 4 -_main: -main: - -sub sp, sp, 32 -mov x8, 63 -mov x2, 32 -add x1, sp, 0 -mov x0, 0 -svc 0 -mov x8, 64 -mov x2, 14 -add x1, sp, 0 -mov x0, 1 -svc 0 -mov x8, 93 -svc 0 diff --git a/tests/print/print.arm.s b/tests/print/print.arm.s deleted file mode 100644 index 9b48c8a..0000000 --- a/tests/print/print.arm.s +++ /dev/null @@ -1,36 +0,0 @@ - -buf: - .string "hello world\n" - - -.text - -.global _start -.global _main - -.balign 4 -_start: -bl main -mov x8, #93 -svc #0 - -.balign 4 -_main: -main: - -mov x3, 1000 -.loop: -sub x3, x3, 1 -cmp x3, xzr -ble .end -mov x8, 64 -mov x2, 14 -adrp x0, buf -add x1, x0, :lo12:buf -mov x0, 1 -svc 0 -b .loop -.end: -mov x8, 93 -mov x0, 0 -svc 0