Merge branch 'riscv-gnu-toolchain-update'

This commit is contained in:
Clifford Wolf 2017-01-15 16:57:22 +01:00
commit 6f866fc1c8
13 changed files with 458 additions and 90 deletions

View File

@ -1,13 +1,13 @@
RISCV_GNU_TOOLCHAIN_REV = 7e48594 RISCV_GNU_TOOLCHAIN_GIT_REVISION = 914224e
NEWLIB_URL = ftp://sourceware.org/pub/newlib/newlib-2.2.0.tar.gz RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX = /opt/riscv32
SHELL = bash SHELL = bash
TEST_OBJS = $(addsuffix .o,$(basename $(wildcard tests/*.S))) TEST_OBJS = $(addsuffix .o,$(basename $(wildcard tests/*.S)))
FIRMWARE_OBJS = firmware/start.o firmware/irq.o firmware/print.o firmware/sieve.o firmware/multest.o firmware/stats.o FIRMWARE_OBJS = firmware/start.o firmware/irq.o firmware/print.o firmware/sieve.o firmware/multest.o firmware/stats.o
GCC_WARNS = -Werror -Wall -Wextra -Wshadow -Wundef -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings GCC_WARNS = -Werror -Wall -Wextra -Wshadow -Wundef -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings
GCC_WARNS += -Wredundant-decls -Wstrict-prototypes -Wmissing-prototypes -pedantic # -Wconversion GCC_WARNS += -Wredundant-decls -Wstrict-prototypes -Wmissing-prototypes -pedantic # -Wconversion
TOOLCHAIN_PREFIX = /opt/riscv32i/bin/riscv32-unknown-elf- TOOLCHAIN_PREFIX = $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX)i/bin/riscv32-unknown-elf-
COMPRESSED_ISA = C COMPRESSED_ISA = C
test: testbench.vvp firmware/firmware.hex test: testbench.vvp firmware/firmware.hex
@ -63,26 +63,24 @@ firmware/firmware.bin: firmware/firmware.elf
chmod -x $@ chmod -x $@
firmware/firmware.elf: $(FIRMWARE_OBJS) $(TEST_OBJS) firmware/sections.lds firmware/firmware.elf: $(FIRMWARE_OBJS) $(TEST_OBJS) firmware/sections.lds
$(TOOLCHAIN_PREFIX)gcc -Os -m32 -ffreestanding -nostdlib -o $@ \ $(TOOLCHAIN_PREFIX)gcc -Os -ffreestanding -nostdlib -o $@ \
-Wl,-Bstatic,-T,firmware/sections.lds,-Map,firmware/firmware.map,--strip-debug \ -Wl,-Bstatic,-T,firmware/sections.lds,-Map,firmware/firmware.map,--strip-debug \
$(FIRMWARE_OBJS) $(TEST_OBJS) -lgcc $(FIRMWARE_OBJS) $(TEST_OBJS) -lgcc
chmod -x $@ chmod -x $@
firmware/start.o: firmware/start.S firmware/start.o: firmware/start.S
$(TOOLCHAIN_PREFIX)gcc -c -m32 -march=RV32IM$(COMPRESSED_ISA)Xcustom -o $@ $< $(TOOLCHAIN_PREFIX)gcc -c -march=rv32im$(subst C,c,$(COMPRESSED_ISA)) -o $@ $<
firmware/%.o: firmware/%.c firmware/%.o: firmware/%.c
$(TOOLCHAIN_PREFIX)gcc -c -m32 -march=RV32I$(COMPRESSED_ISA) -Os --std=c99 $(GCC_WARNS) -ffreestanding -nostdlib -o $@ $< $(TOOLCHAIN_PREFIX)gcc -c -march=rv32i$(subst C,c,$(COMPRESSED_ISA)) -Os --std=c99 $(GCC_WARNS) -ffreestanding -nostdlib -o $@ $<
tests/%.o: tests/%.S tests/riscv_test.h tests/test_macros.h tests/%.o: tests/%.S tests/riscv_test.h tests/test_macros.h
$(TOOLCHAIN_PREFIX)gcc -c -m32 -march=RV32IM -o $@ -DTEST_FUNC_NAME=$(notdir $(basename $<)) \ $(TOOLCHAIN_PREFIX)gcc -c -march=rv32im -o $@ -DTEST_FUNC_NAME=$(notdir $(basename $<)) \
-DTEST_FUNC_TXT='"$(notdir $(basename $<))"' -DTEST_FUNC_RET=$(notdir $(basename $<))_ret $< -DTEST_FUNC_TXT='"$(notdir $(basename $<))"' -DTEST_FUNC_RET=$(notdir $(basename $<))_ret $<
download-tools: download-tools:
sudo bash -c 'set -ex; mkdir -p /var/cache/distfiles; $(foreach URL,$(NEWLIB_URL), \ sudo bash -c 'set -ex; mkdir -p /var/cache/distfiles; \
if ! test -f /var/cache/distfiles/$(notdir $(URL)); then wget -O /var/cache/distfiles/$(notdir $(URL)).part $(URL); \ $(foreach REPO,riscv-gnu-toolchain riscv-binutils-gdb riscv-dejagnu riscv-gcc riscv-glibc riscv-newlib, \
mv /var/cache/distfiles/$(notdir $(URL)).part /var/cache/distfiles/$(notdir $(URL)); fi;) \
$(foreach REPO,riscv-gnu-toolchain riscv-binutils-gdb riscv-dejagnu riscv-gcc riscv-glibc, \
if ! test -d /var/cache/distfiles/$(REPO).git; then rm -rf /var/cache/distfiles/$(REPO).git.part; \ if ! test -d /var/cache/distfiles/$(REPO).git; then rm -rf /var/cache/distfiles/$(REPO).git.part; \
git clone --bare https://github.com/riscv/$(REPO) /var/cache/distfiles/$(REPO).git.part; \ git clone --bare https://github.com/riscv/$(REPO) /var/cache/distfiles/$(REPO).git.part; \
mv /var/cache/distfiles/$(REPO).git.part /var/cache/distfiles/$(REPO).git; else \ mv /var/cache/distfiles/$(REPO).git.part /var/cache/distfiles/$(REPO).git; else \
@ -90,9 +88,9 @@ download-tools:
define build_tools_template define build_tools_template
build-$(1)-tools: build-$(1)-tools:
@read -p "This will remove all existing data from /opt/$(1). Type YES to continue: " reply && [[ "$$$$reply" == [Yy][Ee][Ss] || "$$$$reply" == [Yy] ]] @read -p "This will remove all existing data from $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX)$(subst riscv32,,$(1)). Type YES to continue: " reply && [[ "$$$$reply" == [Yy][Ee][Ss] || "$$$$reply" == [Yy] ]]
sudo bash -c "set -ex; rm -rf /opt/$(1); mkdir -p /opt/$(1); chown $$$${USER}. /opt/$(1)" sudo bash -c "set -ex; rm -rf $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX)$(subst riscv32,,$(1)); mkdir -p $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX)$(subst riscv32,,$(1)); chown $$$${USER}. $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX)$(subst riscv32,,$(1))"
$(MAKE) build-$(1)-tools-bh +$(MAKE) build-$(1)-tools-bh
build-$(1)-tools-bh: build-$(1)-tools-bh:
+set -ex; \ +set -ex; \
@ -101,30 +99,32 @@ build-$(1)-tools-bh:
if [ -d /var/cache/distfiles/riscv-dejagnu.git ]; then reference_riscv_dejagnu="--reference /var/cache/distfiles/riscv-dejagnu.git"; else reference_riscv_dejagnu=""; fi; \ if [ -d /var/cache/distfiles/riscv-dejagnu.git ]; then reference_riscv_dejagnu="--reference /var/cache/distfiles/riscv-dejagnu.git"; else reference_riscv_dejagnu=""; fi; \
if [ -d /var/cache/distfiles/riscv-gcc.git ]; then reference_riscv_gcc="--reference /var/cache/distfiles/riscv-gcc.git"; else reference_riscv_gcc=""; fi; \ if [ -d /var/cache/distfiles/riscv-gcc.git ]; then reference_riscv_gcc="--reference /var/cache/distfiles/riscv-gcc.git"; else reference_riscv_gcc=""; fi; \
if [ -d /var/cache/distfiles/riscv-glibc.git ]; then reference_riscv_glibc="--reference /var/cache/distfiles/riscv-glibc.git"; else reference_riscv_glibc=""; fi; \ if [ -d /var/cache/distfiles/riscv-glibc.git ]; then reference_riscv_glibc="--reference /var/cache/distfiles/riscv-glibc.git"; else reference_riscv_glibc=""; fi; \
if [ -d /var/cache/distfiles/riscv-newlib.git ]; then reference_riscv_newlib="--reference /var/cache/distfiles/riscv-newlib.git"; else reference_riscv_newlib=""; fi; \
rm -rf riscv-gnu-toolchain-$(1); git clone $$$$reference_riscv_gnu_toolchain https://github.com/riscv/riscv-gnu-toolchain riscv-gnu-toolchain-$(1); \ rm -rf riscv-gnu-toolchain-$(1); git clone $$$$reference_riscv_gnu_toolchain https://github.com/riscv/riscv-gnu-toolchain riscv-gnu-toolchain-$(1); \
cd riscv-gnu-toolchain-$(1); git checkout $(RISCV_GNU_TOOLCHAIN_REV); \ cd riscv-gnu-toolchain-$(1); git checkout $(RISCV_GNU_TOOLCHAIN_GIT_REVISION); \
git submodule update --init $$$$reference_riscv_binutils_gdb riscv-binutils-gdb; \ git submodule update --init $$$$reference_riscv_binutils_gdb riscv-binutils-gdb; \
git submodule update --init $$$$reference_riscv_dejagnu riscv-dejagnu; \ git submodule update --init $$$$reference_riscv_dejagnu riscv-dejagnu; \
git submodule update --init $$$$reference_riscv_gcc riscv-gcc; \ git submodule update --init $$$$reference_riscv_gcc riscv-gcc; \
git submodule update --init $$$$reference_riscv_glibc riscv-glibc; \ git submodule update --init $$$$reference_riscv_glibc riscv-glibc; \
mkdir build; cd build; ../configure --with-arch=$(2) --prefix=/opt/$(1); make git submodule update --init $$$$reference_riscv_newlib riscv-newlib; \
mkdir build; cd build; ../configure --with-arch=$(2) --prefix=$(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX)$(subst riscv32,,$(1)); make
.PHONY: build-$(1)-tools .PHONY: build-$(1)-tools
endef endef
$(eval $(call build_tools_template,riscv32i,RV32I)) $(eval $(call build_tools_template,riscv32i,rv32i))
$(eval $(call build_tools_template,riscv32ic,RV32IC)) $(eval $(call build_tools_template,riscv32ic,rv32ic))
$(eval $(call build_tools_template,riscv32im,RV32IM)) $(eval $(call build_tools_template,riscv32im,rv32im))
$(eval $(call build_tools_template,riscv32imc,RV32IMC)) $(eval $(call build_tools_template,riscv32imc,rv32imc))
build-tools: build-tools:
@echo "This will remove all existing data from /opt/riscv32i, /opt/riscv32ic, /opt/riscv32im, and /opt/riscv32imc." @echo "This will remove all existing data from $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX)i, $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX)ic, $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX)im, and $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX)imc."
@read -p "Type YES to continue: " reply && [[ "$$reply" == [Yy][Ee][Ss] || "$$reply" == [Yy] ]] @read -p "Type YES to continue: " reply && [[ "$$reply" == [Yy][Ee][Ss] || "$$reply" == [Yy] ]]
sudo bash -c "set -ex; rm -rf /opt/riscv32{i,ic,im,imc}; mkdir -p /opt/riscv32{i,ic,im,imc}; chown $${USER}. /opt/riscv32{i,ic,im,imc}" sudo bash -c "set -ex; rm -rf $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX){i,ic,im,imc}; mkdir -p $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX){i,ic,im,imc}; chown $${USER}. $(RISCV_GNU_TOOLCHAIN_INSTALL_PREFIX){i,ic,im,imc}"
$(MAKE) build-riscv32i-tools-bh +$(MAKE) build-riscv32i-tools-bh
$(MAKE) build-riscv32ic-tools-bh +$(MAKE) build-riscv32ic-tools-bh
$(MAKE) build-riscv32im-tools-bh +$(MAKE) build-riscv32im-tools-bh
$(MAKE) build-riscv32imc-tools-bh +$(MAKE) build-riscv32imc-tools-bh
toc: toc:
gawk '/^-+$$/ { y=tolower(x); gsub("[^a-z0-9]+", "-", y); gsub("-$$", "", y); printf("- [%s](#%s)\n", x, y); } { x=$$0; }' README.md gawk '/^-+$$/ { y=tolower(x); gsub("[^a-z0-9]+", "-", y); gsub("-$$", "", y); printf("- [%s](#%s)\n", x, y); } { x=$$0; }' README.md

View File

@ -23,6 +23,7 @@ PicoRV32 is free and open hardware licensed under the [ISC license](http://en.wi
- [Pico Co-Processor Interface (PCPI)](#pico-co-processor-interface-pcpi) - [Pico Co-Processor Interface (PCPI)](#pico-co-processor-interface-pcpi)
- [Custom Instructions for IRQ Handling](#custom-instructions-for-irq-handling) - [Custom Instructions for IRQ Handling](#custom-instructions-for-irq-handling)
- [Building a pure RV32I Toolchain](#building-a-pure-rv32i-toolchain) - [Building a pure RV32I Toolchain](#building-a-pure-rv32i-toolchain)
- [Linking binaries with newlib for PicoRV32](#linking-binaries-with-newlib-for-picorv32)
- [Evaluation: Timing and Utilization on Xilinx 7-Series FPGAs](#evaluation-timing-and-utilization-on-xilinx-7-series-fpgas) - [Evaluation: Timing and Utilization on Xilinx 7-Series FPGAs](#evaluation-timing-and-utilization-on-xilinx-7-series-fpgas)
@ -596,13 +597,18 @@ Example:
Building a pure RV32I Toolchain Building a pure RV32I Toolchain
------------------------------- -------------------------------
TL;DR: Run the following commands to build the complete toolchain:
make download-tools
make -j$(nproc) build-tools
The default settings in the [riscv-tools](https://github.com/riscv/riscv-tools) build The default settings in the [riscv-tools](https://github.com/riscv/riscv-tools) build
scripts will build a compiler, assembler and linker that can target any RISC-V ISA, scripts will build a compiler, assembler and linker that can target any RISC-V ISA,
but the libraries are built for RV32G and RV64G targets. Follow the instructions but the libraries are built for RV32G and RV64G targets. Follow the instructions
below to build a complete toolchain (including libraries) that target a pure RV32I below to build a complete toolchain (including libraries) that target a pure RV32I
CPU. CPU.
The following commands will build the RISC-V gnu toolchain and libraries for a The following commands will build the RISC-V GNU toolchain and libraries for a
pure RV32I target, and install it in `/opt/riscv32i`: pure RV32I target, and install it in `/opt/riscv32i`:
# Ubuntu packages needed: # Ubuntu packages needed:
@ -614,7 +620,7 @@ pure RV32I target, and install it in `/opt/riscv32i`:
git clone https://github.com/riscv/riscv-gnu-toolchain riscv-gnu-toolchain-rv32i git clone https://github.com/riscv/riscv-gnu-toolchain riscv-gnu-toolchain-rv32i
cd riscv-gnu-toolchain-rv32i cd riscv-gnu-toolchain-rv32i
git checkout 7e48594 git checkout 914224e
git submodule update --init --recursive git submodule update --init --recursive
mkdir build; cd build mkdir build; cd build
@ -643,7 +649,25 @@ By default calling any of those make targets will (re-)download the toolchain
sources. Run `make download-tools` to download the sources to `/var/cache/distfiles/` sources. Run `make download-tools` to download the sources to `/var/cache/distfiles/`
once in advance. once in advance.
*Note: This instructions are for git rev 7e48594 (2016-08-16) of riscv-gnu-toolchain.* *Note: This instructions are for git rev 914224e (2017-01-06) of riscv-gnu-toolchain.*
Linking binaries with newlib for PicoRV32
-----------------------------------------
The tool chains (see last section for install instructions) come with a version of
the newlib C standard library.
Use the linker script [firmware/riscv.ld](firmware/riscv.ld) for linking binaries
against the newlib library. Using this linker script will create a binary that
has its entry point at 0x10000. (The default linker script does not have a static
entry point, thus a proper ELF loader would be needed that can determine the
entry point at runtime while loading the program.)
Newlib comes with a few syscall stubs. You need to provide your own implementation
of those syscalls and link your program with this implementation, overwriting the
default stubs from newlib. See `syscalls.c` in [scripts/cxxdemo/](scripts/cxxdemo/)
for an example of how to do that.
Evaluation: Timing and Utilization on Xilinx 7-Series FPGAs Evaluation: Timing and Utilization on Xilinx 7-Series FPGAs

View File

@ -1,6 +1,6 @@
USE_MYSTDLIB = 0 USE_MYSTDLIB = 0
OBJS = dhry_1.o dhry_2.o stdlib.o OBJS = dhry_1.o dhry_2.o stdlib.o
CFLAGS = -MD -O3 -m32 -march=RV32IM -DTIME -DRISCV CFLAGS = -MD -O3 -march=rv32im -DTIME -DRISCV
TOOLCHAIN_PREFIX = /opt/riscv32im/bin/riscv32-unknown-elf- TOOLCHAIN_PREFIX = /opt/riscv32im/bin/riscv32-unknown-elf-
ifeq ($(USE_MYSTDLIB),1) ifeq ($(USE_MYSTDLIB),1)
@ -44,7 +44,7 @@ dhry.elf: $(OBJS) sections.lds
chmod -x $@ chmod -x $@
else else
dhry.elf: $(OBJS) dhry.elf: $(OBJS)
$(TOOLCHAIN_PREFIX)gcc $(CFLAGS) -Wl,-Bstatic,-Map,dhry.map,--strip-debug -o $@ $(OBJS) -lgcc -lc $(TOOLCHAIN_PREFIX)gcc $(CFLAGS) -Wl,-Bstatic,-T,../firmware/riscv.ld,-Map,dhry.map,--strip-debug -o $@ $(OBJS) -lgcc -lc
chmod -x $@ chmod -x $@
endif endif

View File

@ -5,32 +5,98 @@
// binary, for any purpose, commercial or non-commercial, and by any // binary, for any purpose, commercial or non-commercial, and by any
// means. // means.
#define q0 0 #define regnum_q0 0
#define q1 1 #define regnum_q1 1
#define q2 2 #define regnum_q2 2
#define q3 3 #define regnum_q3 3
.macro getq rd qs #define regnum_x0 0
custom0 \rd,\qs,0,0 #define regnum_x1 1
.endm #define regnum_x2 2
#define regnum_x3 3
#define regnum_x4 4
#define regnum_x5 5
#define regnum_x6 6
#define regnum_x7 7
#define regnum_x8 8
#define regnum_x9 9
#define regnum_x10 10
#define regnum_x11 11
#define regnum_x12 12
#define regnum_x13 13
#define regnum_x14 14
#define regnum_x15 15
#define regnum_x16 16
#define regnum_x17 17
#define regnum_x18 18
#define regnum_x19 19
#define regnum_x20 20
#define regnum_x21 21
#define regnum_x22 22
#define regnum_x23 23
#define regnum_x24 24
#define regnum_x25 25
#define regnum_x26 26
#define regnum_x27 27
#define regnum_x28 28
#define regnum_x29 29
#define regnum_x30 30
#define regnum_x31 31
.macro setq qd rs #define regnum_zero 0
custom0 \qd,\rs,0,1 #define regnum_ra 1
.endm #define regnum_sp 2
#define regnum_gp 3
#define regnum_tp 4
#define regnum_t0 5
#define regnum_t1 6
#define regnum_t2 7
#define regnum_s0 8
#define regnum_s1 9
#define regnum_a0 10
#define regnum_a1 11
#define regnum_a2 12
#define regnum_a3 13
#define regnum_a4 14
#define regnum_a5 15
#define regnum_a6 16
#define regnum_a7 17
#define regnum_s2 18
#define regnum_s3 19
#define regnum_s4 20
#define regnum_s5 21
#define regnum_s6 22
#define regnum_s7 23
#define regnum_s8 24
#define regnum_s9 25
#define regnum_s10 26
#define regnum_s11 27
#define regnum_t3 28
#define regnum_t4 29
#define regnum_t5 30
#define regnum_t6 31
.macro retirq // x8 is s0 and also fp
custom0 0,0,0,2 #define regnum_fp 8
.endm
.macro maskirq rd rs #define r_type_insn(_f7, _rs2, _rs1, _f3, _rd, _opc) \
custom0 \rd,\rs,0,3 .word (((_f7) << 25) | ((_rs2) << 20) | ((_rs1) << 15) | ((_f3) << 12) | ((_rd) << 7) | ((_opc) << 0))
.endm
.macro waitirq rd #define picorv32_getq_insn(_rd, _qs) \
custom0 \rd,0,0,4 r_type_insn(0b0000000, 0, regnum_ ## _qs, 0b100, regnum_ ## _rd, 0b0001011)
.endm
.macro timer rd rs #define picorv32_setq_insn(_qd, _rs) \
custom0 \rd,\rs,0,5 r_type_insn(0b0000001, 0, regnum_ ## _rs, 0b010, regnum_ ## _qd, 0b0001011)
.endm
#define picorv32_retirq_insn() \
r_type_insn(0b0000010, 0, 0, 0b000, 0, 0b0001011)
#define picorv32_maskirq_insn(_rd, _rs) \
r_type_insn(0b0000011, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)
#define picorv32_waitirq_insn(_rd) \
r_type_insn(0b0000100, 0, 0, 0b100, regnum_ ## _rd, 0b0001011)
#define picorv32_timer_insn(_rd, _rs) \
r_type_insn(0b0000101, 0, regnum_ ## _rs, 0b110, regnum_ ## _rd, 0b0001011)

200
firmware/riscv.ld Normal file
View File

@ -0,0 +1,200 @@
/* Default linker script, for normal executables */
/* Copyright (C) 2014-2016 Free Software Foundation, Inc.
Copying and distribution of this script, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. */
OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv",
"elf32-littleriscv")
OUTPUT_ARCH(riscv)
ENTRY(_start)
SECTIONS
{
. = 0x00010000;
.text :
{
*(.text)
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(.stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
}
.init :
{
KEEP (*(SORT_NONE(.init)))
}
.plt : { *(.plt) }
.iplt : { *(.iplt) }
.fini :
{
KEEP (*(SORT_NONE(.fini)))
}
PROVIDE (__etext = .);
PROVIDE (_etext = .);
PROVIDE (etext = .);
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
.rodata1 : { *(.rodata1) }
.sdata2 :
{
*(.sdata2 .sdata2.* .gnu.linkonce.s2.*)
}
.sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) }
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table
.gcc_except_table.*) }
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
/* These sections are generated by the Sun/Oracle C++ compiler. */
.exception_ranges : ONLY_IF_RO { *(.exception_ranges
.exception_ranges*) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
/* Exception handling */
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
.exception_ranges : ONLY_IF_RW { *(.exception_ranges .exception_ranges*) }
/* Thread Local Storage sections */
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.preinit_array :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
}
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE_HIDDEN (__init_array_end = .);
}
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
PROVIDE_HIDDEN (__fini_array_end = .);
}
.ctors :
{
/* gcc uses crtbegin.o to find the start of
the constructors, so we make sure it is
first. Because this is a wildcard, it
doesn't matter if the user does not
actually link against crtbegin.o; the
linker won't look for a file to match a
wildcard. The wildcard also means that it
doesn't matter which directory crtbegin.o
is in. */
KEEP (*crtbegin.o(.ctors))
KEEP (*crtbegin?.o(.ctors))
/* We don't want to include the .ctor section from
the crtend.o file until after the sorted ctors.
The .ctor section from the crtend file contains the
end of ctors marker and it must be last */
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
}
.dtors :
{
KEEP (*crtbegin.o(.dtors))
KEEP (*crtbegin?.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
}
.jcr : { KEEP (*(.jcr)) }
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
.dynamic : { *(.dynamic) }
. = DATA_SEGMENT_RELRO_END (0, .);
.data :
{
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
}
.data1 : { *(.data1) }
.got : { *(.got.plt) *(.igot.plt) *(.got) *(.igot) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata :
{
_gp = . + 0x800;
*(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*)
*(.sdata .sdata.* .gnu.linkonce.s.*)
}
_edata = .; PROVIDE (edata = .);
. = .;
__bss_start = .;
.sbss :
{
*(.dynsbss)
*(.sbss .sbss.* .gnu.linkonce.sb.*)
*(.scommon)
}
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections.
FIXME: Why do we need it? When there is no .bss section, we don't
pad the .data section. */
. = ALIGN(. != 0 ? 32 / 8 : 1);
}
. = ALIGN(32 / 8);
. = SEGMENT_START("ldata-segment", .);
. = ALIGN(32 / 8);
_end = .; PROVIDE (end = .);
. = DATA_SEGMENT_END (.);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* DWARF 3 */
.debug_pubtypes 0 : { *(.debug_pubtypes) }
.debug_ranges 0 : { *(.debug_ranges) }
/* DWARF Extension. */
.debug_macro 0 : { *(.debug_macro) }
.debug_addr 0 : { *(.debug_addr) }
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}

90
firmware/riscv_ld.diff Normal file
View File

@ -0,0 +1,90 @@
--- <(riscv32-unknown-elf-ld -z nocombreloc -verbose) 2017-01-13 16:55:07.569030165 +0100
+++ riscv.ld 2017-01-13 16:56:47.796761642 +0100
@@ -1,9 +1,3 @@
-GNU ld (GNU Binutils) 2.28.51.20170101
- Supported emulations:
- elf32lriscv
- elf64lriscv
-using internal linker script:
-==================================================
/* Default linker script, for normal executables */
/* Copyright (C) 2014-2016 Free Software Foundation, Inc.
Copying and distribution of this script, with or without modification,
@@ -13,62 +7,26 @@
"elf32-littleriscv")
OUTPUT_ARCH(riscv)
ENTRY(_start)
-SEARCH_DIR("/opt/new_riscv32i/riscv32-unknown-elf/lib");
SECTIONS
{
- /* Read-only sections, merged into text segment: */
- PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x10000)); . = SEGMENT_START("text-segment", 0x10000) + SIZEOF_HEADERS;
- .interp : { *(.interp) }
- .note.gnu.build-id : { *(.note.gnu.build-id) }
- .hash : { *(.hash) }
- .gnu.hash : { *(.gnu.hash) }
- .dynsym : { *(.dynsym) }
- .dynstr : { *(.dynstr) }
- .gnu.version : { *(.gnu.version) }
- .gnu.version_d : { *(.gnu.version_d) }
- .gnu.version_r : { *(.gnu.version_r) }
- .rela.init : { *(.rela.init) }
- .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
- .rela.fini : { *(.rela.fini) }
- .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
- .rela.data.rel.ro : { *(.rela.data.rel.ro .rela.data.rel.ro.* .rela.gnu.linkonce.d.rel.ro.*) }
- .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
- .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
- .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
- .rela.ctors : { *(.rela.ctors) }
- .rela.dtors : { *(.rela.dtors) }
- .rela.got : { *(.rela.got) }
- .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) }
- .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) }
- .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) }
- .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) }
- .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
- .rela.iplt :
- {
- PROVIDE_HIDDEN (__rela_iplt_start = .);
- *(.rela.iplt)
- PROVIDE_HIDDEN (__rela_iplt_end = .);
- }
- .rela.plt :
- {
- *(.rela.plt)
- }
- .init :
- {
- KEEP (*(SORT_NONE(.init)))
- }
- .plt : { *(.plt) }
- .iplt : { *(.iplt) }
+ . = 0x00010000;
.text :
{
+ *(.text)
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
- *(.text .stub .text.* .gnu.linkonce.t.*)
+ *(.stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
}
+ .init :
+ {
+ KEEP (*(SORT_NONE(.init)))
+ }
+ .plt : { *(.plt) }
+ .iplt : { *(.iplt) }
.fini :
{
KEEP (*(SORT_NONE(.fini)))
@@ -240,5 +198,3 @@
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
}
-
-==================================================

View File

@ -34,8 +34,8 @@
reset_vec: reset_vec:
// no more than 16 bytes here ! // no more than 16 bytes here !
waitirq zero picorv32_waitirq_insn(zero)
maskirq zero, zero picorv32_maskirq_insn(zero, zero)
j start j start
@ -48,19 +48,19 @@ irq_vec:
#ifdef ENABLE_QREGS #ifdef ENABLE_QREGS
setq q2, x1 picorv32_setq_insn(q2, x1)
setq q3, x2 picorv32_setq_insn(q3, x2)
lui x1, %hi(irq_regs) lui x1, %hi(irq_regs)
addi x1, x1, %lo(irq_regs) addi x1, x1, %lo(irq_regs)
getq x2, q0 picorv32_getq_insn(x2, q0)
sw x2, 0*4(x1) sw x2, 0*4(x1)
getq x2, q2 picorv32_getq_insn(x2, q2)
sw x2, 1*4(x1) sw x2, 1*4(x1)
getq x2, q3 picorv32_getq_insn(x2, q3)
sw x2, 2*4(x1) sw x2, 2*4(x1)
#ifdef ENABLE_FASTIRQ #ifdef ENABLE_FASTIRQ
@ -180,7 +180,7 @@ irq_vec:
// arg1 = interrupt type // arg1 = interrupt type
#ifdef ENABLE_QREGS #ifdef ENABLE_QREGS
getq a1, q1 picorv32_getq_insn(a1, q1)
#else #else
addi a1, tp, 0 addi a1, tp, 0
#endif #endif
@ -196,13 +196,13 @@ irq_vec:
addi x1, a0, 0 addi x1, a0, 0
lw x2, 0*4(x1) lw x2, 0*4(x1)
setq q0, x2 picorv32_setq_insn(q0, x2)
lw x2, 1*4(x1) lw x2, 1*4(x1)
setq q1, x2 picorv32_setq_insn(q1, x2)
lw x2, 2*4(x1) lw x2, 2*4(x1)
setq q2, x2 picorv32_setq_insn(q2, x2)
#ifdef ENABLE_FASTIRQ #ifdef ENABLE_FASTIRQ
lw x5, 5*4(x1) lw x5, 5*4(x1)
@ -252,8 +252,8 @@ irq_vec:
lw x31, 31*4(x1) lw x31, 31*4(x1)
#endif #endif
getq x1, q1 picorv32_getq_insn(x1, q1)
getq x2, q2 picorv32_getq_insn(x2, q2)
#else // ENABLE_QREGS #else // ENABLE_QREGS
@ -319,7 +319,7 @@ irq_vec:
#endif // ENABLE_QREGS #endif // ENABLE_QREGS
retirq picorv32_retirq_insn()
#ifndef ENABLE_QREGS #ifndef ENABLE_QREGS
.balign 0x200 .balign 0x200
@ -378,7 +378,7 @@ start:
# define TEST(n) \ # define TEST(n) \
.global n; \ .global n; \
addi x1, zero, 1000; \ addi x1, zero, 1000; \
timer zero, x1; \ picorv32_timer_insn(zero, x1); \
jal zero,n; \ jal zero,n; \
.global n ## _ret; \ .global n ## _ret; \
n ## _ret: n ## _ret:

View File

@ -22,7 +22,7 @@ firmware32.hex: firmware.elf start.elf hex8tohex32.py
rm -f start.tmp firmware.tmp rm -f start.tmp firmware.tmp
firmware.elf: firmware.o syscalls.o firmware.elf: firmware.o syscalls.o
$(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) $(CC) $(LDFLAGS) -o $@ $^ -T ../../firmware/riscv.ld $(LDLIBS)
chmod -x firmware.elf chmod -x firmware.elf
start.elf: start.S start.ld start.elf: start.S start.ld

View File

@ -22,10 +22,10 @@ RVTEST_CODE_BEGIN
TEST_RR_OP( 4, div, -3, 20, -6 ); TEST_RR_OP( 4, div, -3, 20, -6 );
TEST_RR_OP( 5, div, 3, -20, -6 ); TEST_RR_OP( 5, div, 3, -20, -6 );
TEST_RR_OP( 6, div, -1<<63, -1<<63, 1 ); TEST_RR_OP( 6, div, -1<<31, -1<<31, 1 );
TEST_RR_OP( 7, div, -1<<63, -1<<63, -1 ); TEST_RR_OP( 7, div, -1<<31, -1<<31, -1 );
TEST_RR_OP( 8, div, -1, -1<<63, 0 ); TEST_RR_OP( 8, div, -1, -1<<31, 0 );
TEST_RR_OP( 9, div, -1, 1, 0 ); TEST_RR_OP( 9, div, -1, 1, 0 );
TEST_RR_OP(10, div, -1, 0, 0 ); TEST_RR_OP(10, div, -1, 0, 0 );

View File

@ -22,10 +22,10 @@ RVTEST_CODE_BEGIN
TEST_RR_OP( 4, rem, 2, 20, -6 ); TEST_RR_OP( 4, rem, 2, 20, -6 );
TEST_RR_OP( 5, rem, -2, -20, -6 ); TEST_RR_OP( 5, rem, -2, -20, -6 );
TEST_RR_OP( 6, rem, 0, -1<<63, 1 ); TEST_RR_OP( 6, rem, 0, -1<<31, 1 );
TEST_RR_OP( 7, rem, 0, -1<<63, -1 ); TEST_RR_OP( 7, rem, 0, -1<<31, -1 );
TEST_RR_OP( 8, rem, -1<<63, -1<<63, 0 ); TEST_RR_OP( 8, rem, -1<<31, -1<<31, 0 );
TEST_RR_OP( 9, rem, 1, 1, 0 ); TEST_RR_OP( 9, rem, 1, 1, 0 );
TEST_RR_OP(10, rem, 0, 0, 0 ); TEST_RR_OP(10, rem, 0, 0, 0 );

View File

@ -22,10 +22,10 @@ RVTEST_CODE_BEGIN
TEST_RR_OP( 4, remu, 20, 20, -6 ); TEST_RR_OP( 4, remu, 20, 20, -6 );
TEST_RR_OP( 5, remu, -20, -20, -6 ); TEST_RR_OP( 5, remu, -20, -20, -6 );
TEST_RR_OP( 6, remu, 0, -1<<63, 1 ); TEST_RR_OP( 6, remu, 0, -1<<31, 1 );
TEST_RR_OP( 7, remu, -1<<63, -1<<63, -1 ); TEST_RR_OP( 7, remu, -1<<31, -1<<31, -1 );
TEST_RR_OP( 8, remu, -1<<63, -1<<63, 0 ); TEST_RR_OP( 8, remu, -1<<31, -1<<31, 0 );
TEST_RR_OP( 9, remu, 1, 1, 0 ); TEST_RR_OP( 9, remu, 1, 1, 0 );
TEST_RR_OP(10, remu, 0, 0, 0 ); TEST_RR_OP(10, remu, 0, 0, 0 );

View File

@ -19,13 +19,7 @@ RVTEST_CODE_BEGIN
TEST_ST_OP( 2, lb, sb, 0xffffffaa, 0, tdat ); TEST_ST_OP( 2, lb, sb, 0xffffffaa, 0, tdat );
TEST_ST_OP( 3, lb, sb, 0x00000000, 1, tdat ); TEST_ST_OP( 3, lb, sb, 0x00000000, 1, tdat );
#ifdef __RISCVEL
TEST_ST_OP( 4, lh, sb, 0xffffefa0, 2, tdat ); TEST_ST_OP( 4, lh, sb, 0xffffefa0, 2, tdat );
#elif defined(__RISCVEB)
#else
TEST_ST_OP( 4, lh, sb, 0xffffa0ef, 2, tdat );
#error unknown endianness!
#endif
TEST_ST_OP( 5, lb, sb, 0x0000000a, 3, tdat ); TEST_ST_OP( 5, lb, sb, 0x0000000a, 3, tdat );
# Test with negative offset # Test with negative offset

View File

@ -19,13 +19,7 @@ RVTEST_CODE_BEGIN
TEST_ST_OP( 2, lh, sh, 0x000000aa, 0, tdat ); TEST_ST_OP( 2, lh, sh, 0x000000aa, 0, tdat );
TEST_ST_OP( 3, lh, sh, 0xffffaa00, 2, tdat ); TEST_ST_OP( 3, lh, sh, 0xffffaa00, 2, tdat );
#ifdef __RISCVEL
TEST_ST_OP( 4, lw, sh, 0xbeef0aa0, 4, tdat ); TEST_ST_OP( 4, lw, sh, 0xbeef0aa0, 4, tdat );
#elif defined(__RISCVEB)
#else
TEST_ST_OP( 4, lw, sh, 0x0aa0beef, 4, tdat );
#error unknown endianness!
#endif
TEST_ST_OP( 5, lh, sh, 0xffffa00a, 6, tdat ); TEST_ST_OP( 5, lh, sh, 0xffffa00a, 6, tdat );
# Test with negative offset # Test with negative offset