diff --git a/.gitignore b/.gitignore index 161d7f2..36fa30f 100644 --- a/.gitignore +++ b/.gitignore @@ -26,6 +26,9 @@ Cargo.lock # temporary files *.bin +*.arm.s +*.as +a.out .vscode/ test_binary_translate* \ No newline at end of file diff --git a/run.sh b/run.sh index 31240d2..10e1bea 100755 --- a/run.sh +++ b/run.sh @@ -1,18 +1,34 @@ #!/usr/bin/env bash -ASM_FILE=$1 +ARCH=$1 +ASM_FILE=$2 PLATFORM="" LD_FLAGS="" -BENCHMARKING="false" # "true" to enable +BENCHMARKING="true" # "true" to enable +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="aarch64-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 @@ -23,9 +39,10 @@ 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/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 deleted file mode 100644 index 391c523..0000000 --- a/tests/add/add.arm.s +++ /dev/null @@ -1,34 +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 -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/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 a2686d3..1696077 100644 --- a/tests/add/test_add.rs +++ b/tests/add/test_add.rs @@ -4,12 +4,14 @@ 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() }, + RiscVInstruction::Verbatim { + text: ARM_LOOP_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.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/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.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 3a391c7..0000000 --- a/tests/binaries/riscv/flake.nix +++ /dev/null @@ -1,26 +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 - # pkgs.clang-tools - ]; - }; - }; -} 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/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 deleted file mode 100644 index 392f418..0000000 --- a/tests/print/print.arm.s +++ /dev/null @@ -1,28 +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 x8, 64 -mov x2, 14 -adrp x0, .buf -add x1, x0, :lo12:.buf -mov x0, 1 -svc 0 -mov x8, 93 -svc 0 diff --git a/tests/print/print.riscv.s b/tests/print/print.riscv.s new file mode 100644 index 0000000..66cdfc8 --- /dev/null +++ b/tests/print/print.riscv.s @@ -0,0 +1,40 @@ +buf: + .string "Hello world!\n" + +.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 + + 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,