Browse Source

Merge #17

17: Build on stable r=dvc94ch a=Disasm

Closes #14 

cc @rust-embedded/riscv 

Co-authored-by: Vadim Kaushan <admin@disasm.info>
bors[bot] 6 years ago
parent
commit
11367b635e

+ 3 - 0
riscv-rt/.gitignore

@@ -1,2 +1,5 @@
 Cargo.lock
 target/
+bin/*.after
+bin/*.before
+bin/*.o

+ 9 - 0
riscv-rt/.travis.yml

@@ -24,10 +24,19 @@ matrix:
       rust: nightly
       if: (branch = staging OR branch = trying OR branch = master) OR (type = pull_request AND branch = master)
 
+    - env: TARGET=x86_64-unknown-linux-gnu
+      rust: stable
+      if: (branch = staging OR branch = trying OR branch = master) OR (type = pull_request AND branch = master)
+
+    - env: TARGET=riscv32imac-unknown-none-elf
+      rust: stable
+      if: (branch = staging OR branch = trying OR branch = master) OR (type = pull_request AND branch = master)
+
 before_install: set -e
 
 install:
   - bash ci/install.sh
+  - export PATH="$PATH:$PWD/gcc/bin"
 
 script:
   - bash ci/script.sh

+ 3 - 2
riscv-rt/Cargo.toml

@@ -10,7 +10,8 @@ license = "ISC"
 
 [dependencies]
 r0 = "0.2.2"
-riscv = "0.3.0"
+riscv = "0.4.0"
 
 [features]
-inline-asm = []
+const-fn = ["riscv/const-fn"]
+inline-asm = ["riscv/inline-asm"]

+ 89 - 0
riscv-rt/asm.S

@@ -0,0 +1,89 @@
+/*
+    Entry point of all programs (_start).
+
+    It initializes DWARF call frame information, the stack pointer, the
+    frame pointer (needed for closures to work in start_rust) and the global
+    pointer. Then it calls _start_rust.
+*/
+
+.section .init, "ax"
+.global _start
+
+_start:
+    .cfi_startproc
+    .cfi_undefined ra
+
+    // .option push
+    // .option norelax
+    lui gp, %hi(__global_pointer$)
+    addi gp, gp, %lo(__global_pointer$)
+    // .option pop
+
+    lui sp, %hi(_stack_start)
+    addi sp, sp, %lo(_stack_start)
+
+    add s0, sp, zero
+
+    jal zero, _start_rust
+
+    .cfi_endproc
+
+
+/*
+    Trap entry point (_start_trap)
+
+    Saves caller saved registers ra, t0..6, a0..7, calls _start_trap_rust,
+    restores caller saved registers and then returns.
+*/
+.section .trap, "ax"
+.align 4
+.global _start_trap
+
+_start_trap:
+    addi sp, sp, -16*4
+
+    sw ra, 0*4(sp)
+    sw t0, 1*4(sp)
+    sw t1, 2*4(sp)
+    sw t2, 3*4(sp)
+    sw t3, 4*4(sp)
+    sw t4, 5*4(sp)
+    sw t5, 6*4(sp)
+    sw t6, 7*4(sp)
+    sw a0, 8*4(sp)
+    sw a1, 9*4(sp)
+    sw a2, 10*4(sp)
+    sw a3, 11*4(sp)
+    sw a4, 12*4(sp)
+    sw a5, 13*4(sp)
+    sw a6, 14*4(sp)
+    sw a7, 15*4(sp)
+
+    jal ra, _start_trap_rust
+
+    lw ra, 0*4(sp)
+    lw t0, 1*4(sp)
+    lw t1, 2*4(sp)
+    lw t2, 3*4(sp)
+    lw t3, 4*4(sp)
+    lw t4, 5*4(sp)
+    lw t5, 6*4(sp)
+    lw t6, 7*4(sp)
+    lw a0, 8*4(sp)
+    lw a1, 9*4(sp)
+    lw a2, 10*4(sp)
+    lw a3, 11*4(sp)
+    lw a4, 12*4(sp)
+    lw a5, 13*4(sp)
+    lw a6, 14*4(sp)
+    lw a7, 15*4(sp)
+
+    addi sp, sp, 16*4
+    mret
+
+
+/* Make sure there is an abort when linking */
+.section .init
+.globl abort
+abort:
+    jal zero, _start

+ 14 - 0
riscv-rt/assemble.sh

@@ -0,0 +1,14 @@
+#!/bin/bash
+
+set -euxo pipefail
+
+crate=riscv-rt
+
+# 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
+ar crs bin/riscv32imac-unknown-none-elf.a bin/$crate.o
+cp bin/riscv32imac-unknown-none-elf.a bin/riscv32imc-unknown-none-elf.a
+
+rm bin/$crate.o

BIN
riscv-rt/bin/riscv32imac-unknown-none-elf.a


BIN
riscv-rt/bin/riscv32imc-unknown-none-elf.a


+ 17 - 4
riscv-rt/build.rs

@@ -1,17 +1,30 @@
 // NOTE: Adapted from cortex-m/build.rs
 use std::env;
-use std::fs::File;
+use std::fs;
 use std::io::Write;
 use std::path::PathBuf;
 
 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") {
+        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());
+    }
+
     // Put the linker script somewhere the linker can find it
-    let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
-    File::create(out.join("link.x"))
+    fs::File::create(out_dir.join("link.x"))
         .unwrap()
         .write_all(include_bytes!("link.x"))
         .unwrap();
-    println!("cargo:rustc-link-search={}", out.display());
+    println!("cargo:rustc-link-search={}", out_dir.display());
 
     println!("cargo:rerun-if-changed=build.rs");
     println!("cargo:rerun-if-changed=link.x");

+ 21 - 0
riscv-rt/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

+ 3 - 0
riscv-rt/ci/install.sh

@@ -4,6 +4,9 @@ main() {
     if [ $TARGET != x86_64-unknown-linux-gnu ]; then
         rustup target add $TARGET
     fi
+
+    mkdir gcc
+    curl -L https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.1.0-2018.12.0-x86_64-linux-ubuntu14.tar.gz | tar --strip-components=1 -C gcc -xz
 }
 
 main

+ 5 - 1
riscv-rt/ci/script.sh

@@ -4,7 +4,11 @@ main() {
     cargo check --target $TARGET
 
     if [ $TRAVIS_RUST_VERSION = nightly ]; then
-        cargo check --target $TARGET --features inline-asm
+        cargo check --target $TARGET --features 'const-fn inline-asm'
+    fi
+
+    if [ $TARGET = x86_64-unknown-linux-gnu ]; then
+        ./check-blobs.sh
     fi
 }
 

+ 2 - 0
riscv-rt/link.x

@@ -3,6 +3,8 @@ INCLUDE memory.x
 
 PROVIDE(_stack_start = ORIGIN(RAM) + LENGTH(RAM));
 
+PROVIDE(trap_handler = default_trap_handler);
+
 SECTIONS
 {
   PROVIDE(_stext = ORIGIN(FLASH));

+ 0 - 53
riscv-rt/src/lang_items.rs

@@ -1,53 +0,0 @@
-// NOTE: Adapted from cortex-m/src/lang_items.rs
-
-use riscv::asm;
-
-/// Default panic handler
-#[panic_handler]
-fn panic(_info: &core::panic::PanicInfo) -> ! {
-    asm::ebreak();
-    loop {}
-}
-
-/// Lang item required to make the normal `main` work in applications
-// This is how the `start` lang item works:
-// When `rustc` compiles a binary crate, it creates a `main` function that looks
-// like this:
-//
-// ```
-// #[export_name = "main"]
-// pub extern "C" fn rustc_main(argc: isize, argv: *const *const u8) -> isize {
-//     start(main)
-// }
-// ```
-//
-// Where `start` is this function and `main` is the binary crate's `main`
-// function.
-//
-// The final piece is that the entry point of our program, the reset handler,
-// has to call `rustc_main`. That's covered by the `reset_handler` function in
-// root of this crate.
-#[lang = "start"]
-extern "C" fn lang_start<T>(
-    main: fn(),
-    _argc: isize,
-    _argv: *const *const u8,
-) -> isize
-    where
-    T: Termination,
-{
-    main();
-
-    0
-}
-
-#[lang = "termination"]
-pub trait Termination {
-    fn report(self) -> i32;
-}
-
-impl Termination for () {
-    fn report(self) -> i32 {
-        0
-    }
-}

+ 12 - 117
riscv-rt/src/lib.rs

@@ -164,19 +164,11 @@
 #![no_std]
 #![deny(missing_docs)]
 #![deny(warnings)]
-#![feature(asm)]
-#![feature(compiler_builtins_lib)]
-#![feature(const_fn)]
-#![feature(global_asm)]
-#![feature(lang_items)]
-#![feature(linkage)]
 
 extern crate riscv;
 extern crate r0;
 
-mod lang_items;
-
-use riscv::register::{mcause, mstatus};
+use riscv::register::{mstatus, mtvec};
 
 extern "C" {
     // Boundaries of the .bss section
@@ -195,36 +187,6 @@ extern "C" {
 }
 
 
-/// Entry point of all programs (_start).
-///
-/// It initializes DWARF call frame information, the stack pointer, the
-/// frame pointer (needed for closures to work in start_rust) and the global
-/// pointer. Then it calls _start_rust.
-#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
-global_asm!(r#"
-.section .init, "ax"
-.globl _start
-_start:
-  .cfi_startproc
-  .cfi_undefined ra
-
-  // .option push
-  // .option norelax
-  lui gp, %hi(__global_pointer$)
-  addi gp, gp, %lo(__global_pointer$)
-  // .option pop
-
-  lui sp, %hi(_stack_start)
-  addi sp, sp, %lo(_stack_start)
-
-  add s0, sp, zero
-
-  jal zero, _start_rust
-
-  .cfi_endproc
-"#);
-
-
 /// Rust entry point (_start_rust)
 ///
 /// Zeros bss section, initializes data section and calls main. This function
@@ -244,18 +206,10 @@ pub extern "C" fn start_rust() -> ! {
 
     // TODO: Enable FPU when available
 
-    // Set mtvec to _start_trap
-    #[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
     unsafe {
-        //mtvec::write(_start_trap as usize, mtvec::TrapMode::Direct);
-        asm!("csrrw zero, 0x305, $0"
-             :
-             : "r"(&_start_trap)
-             :
-             : "volatile");
-    }
+        // Set mtvec to _start_trap
+        mtvec::write(_start_trap as usize, mtvec::TrapMode::Direct);
 
-    unsafe {
         main();
     }
 }
@@ -286,60 +240,6 @@ macro_rules! entry {
 }
 
 
-/// Trap entry point (_start_trap)
-///
-/// Saves caller saved registers ra, t0..6, a0..7, calls _start_trap_rust,
-/// restores caller saved registers and then returns.
-#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
-global_asm!(r#"
-  .section .trap, "ax"
-  .align 4
-  .global _start_trap
-
-_start_trap:
-  addi sp, sp, -16*4
-
-  sw ra, 0*4(sp)
-  sw t0, 1*4(sp)
-  sw t1, 2*4(sp)
-  sw t2, 3*4(sp)
-  sw t3, 4*4(sp)
-  sw t4, 5*4(sp)
-  sw t5, 6*4(sp)
-  sw t6, 7*4(sp)
-  sw a0, 8*4(sp)
-  sw a1, 9*4(sp)
-  sw a2, 10*4(sp)
-  sw a3, 11*4(sp)
-  sw a4, 12*4(sp)
-  sw a5, 13*4(sp)
-  sw a6, 14*4(sp)
-  sw a7, 15*4(sp)
-
-  jal ra, _start_trap_rust
-
-  lw ra, 0*4(sp)
-  lw t0, 1*4(sp)
-  lw t1, 2*4(sp)
-  lw t2, 3*4(sp)
-  lw t3, 4*4(sp)
-  lw t4, 5*4(sp)
-  lw t5, 6*4(sp)
-  lw t6, 7*4(sp)
-  lw a0, 8*4(sp)
-  lw a1, 9*4(sp)
-  lw a2, 10*4(sp)
-  lw a3, 11*4(sp)
-  lw a4, 12*4(sp)
-  lw a5, 13*4(sp)
-  lw a6, 14*4(sp)
-  lw a7, 15*4(sp)
-
-  addi sp, sp, 16*4
-  mret
-"#);
-
-
 /// Trap entry point rust (_start_trap_rust)
 ///
 /// mcause is read to determine the cause of the trap. XLEN-1 bit indicates
@@ -349,10 +249,15 @@ _start_trap:
 #[link_section = ".trap.rust"]
 #[export_name = "_start_trap_rust"]
 pub extern "C" fn start_trap_rust() {
-    // dispatch trap to handler
-    trap_handler(mcause::read().cause());
-    // mstatus, remain in M-mode after mret
+    extern "C" {
+        fn trap_handler();
+    }
+
     unsafe {
+        // dispatch trap to handler
+        trap_handler();
+
+        // mstatus, remain in M-mode after mret
         mstatus::set_mpp(mstatus::MPP::Machine);
     }
 }
@@ -360,14 +265,4 @@ pub extern "C" fn start_trap_rust() {
 
 /// Default Trap Handler
 #[no_mangle]
-#[linkage = "weak"]
-pub fn trap_handler(_: mcause::Trap) {}
-
-// Make sure there is an abort when linking
-#[cfg(any(target_arch = "riscv32", target_arch = "riscv64"))]
-global_asm!(r#"
-.section .init
-.globl abort
-abort:
-  jal zero, _start
-"#);
+pub fn default_trap_handler() {}