diff --git a/.gitignore b/.gitignore index 1e7caa9..e38997a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ Cargo.lock target/ +bin/*.after +bin/*.before +bin/*.o diff --git a/asm.S b/asm.S new file mode 100644 index 0000000..030dfd1 --- /dev/null +++ b/asm.S @@ -0,0 +1,55 @@ +#include "asm.h" + +.section .text.__ebreak +.global __ebreak +__ebreak: + ebreak + ret + +.section .text.__wfi +.global __wfi +__wfi: + wfi + ret + +.section .text.__sfence_vma_all +.global __sfence_vma_all +__sfence_vma_all: + sfence.vma + ret + +.section .text.__sfence_vma +.global __sfence_vma +__sfence_vma: + sfence.vma a0, a1 + ret + + +// M-mode registers +REG_READ(mcause, 0x342) +REG_READ(mcycle, 0xB00) +REG_READ(mepc, 0x341) +REG_READ(mie, 0x304) +REG_SET_CLEAR(mie, 0x304) +REG_READ(minstret, 0xB02) +REG_READ(mip, 0x344) +REG_READ(misa, 0x301) +REG_READ(mstatus, 0x300) +REG_SET_CLEAR(mstatus, 0x300) +REG_READ_WRITE(mtvec, 0x305) +REG_READ(mvendorid, 0xF11) + +// S-mode registers +REG_READ_WRITE(satp, 0x180) +REG_READ(scause, 0x142) +REG_READ_WRITE(sepc, 0x141) +REG_READ(sie, 0x104) +REG_SET_CLEAR(sie, 0x104) +REG_READ(sip, 0x144) +REG_READ_WRITE(sscratch, 0x140) +REG_READ(sstatus, 0x100) +REG_SET_CLEAR(sstatus, 0x100) +REG_READ(stval, 0x143) +REG_READ_WRITE(stvec, 0x105) + +REG_READ(time, 0xC01) diff --git a/asm.h b/asm.h new file mode 100644 index 0000000..3ec97f2 --- /dev/null +++ b/asm.h @@ -0,0 +1,37 @@ +#ifndef __ASM_H +#define __ASM_H + +#define REG_READ(name, offset) \ +.section .text.__read_ ## name; \ +.global __read_ ## name; \ +__read_ ## name: \ + csrrs a0, offset, x0; \ + ret + +#define REG_WRITE(name, offset) \ +.section .text.__write_ ## name; \ +.global __write_ ## name; \ +__write_ ## name: \ + csrrw x0, offset, a0; \ + ret + +#define REG_SET(name, offset) \ +.section .text.__set_ ## name; \ +.global __set_ ## name; \ +__set_ ## name: \ + csrrs x0, offset, a0; \ + ret + +#define REG_CLEAR(name, offset) \ +.section .text.__clear_ ## name; \ +.global __clear_ ## name; \ +__clear_ ## name: \ + csrrc x0, offset, a0; \ + ret + + +#define REG_READ_WRITE(name, offset) REG_READ(name, offset); REG_WRITE(name, offset) +#define REG_SET_CLEAR(name, offset) REG_SET(name, offset); REG_CLEAR(name, offset) + +#endif /* __ASM_H */ + diff --git a/asm32.S b/asm32.S new file mode 100644 index 0000000..c163b64 --- /dev/null +++ b/asm32.S @@ -0,0 +1,5 @@ +#include "asm.h" + +REG_READ(mcycleh, 0xB80) +REG_READ(minstreth, 0xB82) +REG_READ(timeh, 0xC81) diff --git a/assemble.sh b/assemble.sh new file mode 100755 index 0000000..30e6fd2 --- /dev/null +++ b/assemble.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +set -euxo pipefail + +crate=riscv + +# remove existing blobs because otherwise this will append object files to the old blobs +rm -f bin/*.a + +riscv64-unknown-elf-gcc -c -mabi=ilp32 -march=rv32imac asm.S -o bin/$crate.o +riscv64-unknown-elf-gcc -c -mabi=ilp32 -march=rv32imac asm32.S -o bin/$crate-32.o +ar crs bin/riscv32imac-unknown-none-elf.a bin/$crate.o bin/$crate-32.o +cp bin/riscv32imac-unknown-none-elf.a bin/riscv32imc-unknown-none-elf.a + +rm bin/$crate.o +rm bin/$crate-32.o diff --git a/bin/riscv32imac-unknown-none-elf.a b/bin/riscv32imac-unknown-none-elf.a new file mode 100644 index 0000000..2346b0c Binary files /dev/null and b/bin/riscv32imac-unknown-none-elf.a differ diff --git a/bin/riscv32imc-unknown-none-elf.a b/bin/riscv32imc-unknown-none-elf.a new file mode 100644 index 0000000..2346b0c Binary files /dev/null and b/bin/riscv32imc-unknown-none-elf.a differ diff --git a/build.rs b/build.rs index 30db72e..965af97 100644 --- a/build.rs +++ b/build.rs @@ -1,7 +1,20 @@ -use std::env; +use std::path::PathBuf; +use std::{env, fs}; fn main() { let target = env::var("TARGET").unwrap(); + let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap()); + let name = env::var("CARGO_PKG_NAME").unwrap(); + + if target.starts_with("riscv") && env::var_os("CARGO_FEATURE_INLINE_ASM").is_none() { + fs::copy( + format!("bin/{}.a", target), + out_dir.join(format!("lib{}.a", name)), + ).unwrap(); + + println!("cargo:rustc-link-lib=static={}", name); + println!("cargo:rustc-link-search={}", out_dir.display()); + } if target.starts_with("riscv32") { println!("cargo:rustc-cfg=riscv"); diff --git a/check-blobs.sh b/check-blobs.sh new file mode 100755 index 0000000..36d885e --- /dev/null +++ b/check-blobs.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +# Checks that the blobs are up to date with the committed assembly files + +set -euxo pipefail + +for lib in $(ls bin/*.a); do + filename=$(basename $lib) + riscv64-unknown-elf-objdump -Cd $lib > bin/${filename%.a}.before +done + +./assemble.sh + +for lib in $(ls bin/*.a); do + filename=$(basename $lib) + riscv64-unknown-elf-objdump -Cd $lib > bin/${filename%.a}.after +done + +for cksum in $(ls bin/*.after); do + diff -u $cksum ${cksum%.after}.before +done