added a whole bunch of interseting test code for branches which does not work.

This commit is contained in:
Ross Thompson 2021-03-23 13:54:29 -05:00
parent 6a050219d4
commit 5edc90b1c2
14 changed files with 844 additions and 1 deletions

23
testsBP/crt0/Makefile Normal file
View File

@ -0,0 +1,23 @@
TARGETDIR := bin
TARGET := $(TARGETDIR)/start
ROOT := ..
LIBRARY_DIRS :=
LIBRARY_FILES :=
LINK_FLAGS := -nostartfiles
AFLAGS =-march=rv64ifd -W
CFLAGS =-march=rv64ifd -mcmodel=medany
AS=riscv64-unknown-elf-as
CC=riscv64-unknown-elf-gcc
AR=riscv64-unknown-elf-ar
all: libcrt0.a
%.o: %.s
${AS} ${AFLAGS} -c $< -o $@
libcrt0.a: start.o
${AR} -r $@ $^
clean:
rm -rf *.a *.o

213
testsBP/crt0/isr.s Normal file
View File

@ -0,0 +1,213 @@
.section .text
.global __trap_handler
.type __trap_handler, @function
__trap_handler:
# save the context of the cpu to the top of the current stack
addi sp, sp, -124
sw x1, 0x0(sp)
sw x2, 0x4(sp)
sw x3, 0x8(sp)
sw x4, 0xC(sp)
sw x5, 0x10(sp)
sw x6, 0x14(sp)
sw x7, 0x18(sp)
sw x8, 0x1C(sp)
sw x9, 0x20(sp)
sw x10, 0x24(sp)
sw x11, 0x28(sp)
sw x12, 0x2C(sp)
sw x13, 0x30(sp)
sw x14, 0x34(sp)
sw x15, 0x38(sp)
sw x16, 0x3C(sp)
sw x17, 0x40(sp)
sw x18, 0x44(sp)
sw x19, 0x48(sp)
sw x20, 0x4C(sp)
sw x21, 0x50(sp)
sw x22, 0x54(sp)
sw x23, 0x58(sp)
sw x24, 0x5C(sp)
sw x25, 0x60(sp)
sw x26, 0x64(sp)
sw x27, 0x68(sp)
sw x28, 0x6C(sp)
sw x29, 0x70(sp)
sw x30, 0x74(sp)
sw x31, 0x78(sp)
# figure out what caused the trap.
csrrw t0, mcause, x0
# mcause is {int, 31 bit exception code}
# for this implementation only the lowest 4 bits are used
srli t1, t0, 31 # interrupt flag
andi t2, t0, 0xF # 4 bit cause
slli t1, t1, 5 # shift int flag
or t1, t1, t2 # combine
slli t1, t1, 2 # multiply by 4
la t3, exception_table
add t4, t3, t1
lw t5, 0(t4)
jr t5, 0 # jump to specific ISR
# specific ISR is expected to set epc
restore_st:
# restore register from stack on exit.
lw x1, 0x0(sp)
lw x2, 0x4(sp)
lw x3, 0x8(sp)
lw x4, 0xC(sp)
lw x5, 0x10(sp)
lw x6, 0x14(sp)
lw x7, 0x18(sp)
lw x8, 0x1C(sp)
lw x9, 0x20(sp)
lw x10, 0x24(sp)
lw x11, 0x28(sp)
lw x12, 0x2C(sp)
lw x13, 0x30(sp)
lw x14, 0x34(sp)
lw x15, 0x38(sp)
lw x16, 0x3C(sp)
lw x17, 0x40(sp)
lw x18, 0x44(sp)
lw x19, 0x48(sp)
lw x20, 0x4C(sp)
lw x21, 0x50(sp)
lw x22, 0x54(sp)
lw x23, 0x58(sp)
lw x24, 0x5C(sp)
lw x25, 0x60(sp)
lw x26, 0x64(sp)
lw x27, 0x68(sp)
lw x28, 0x6C(sp)
lw x29, 0x70(sp)
lw x30, 0x74(sp)
lw x31, 0x78(sp)
addi sp, sp, 124
mret
.section .text
.type trap_instr_addr_misalign, @function
trap_instr_addr_misalign:
# fatal error, report error and halt
addi sp, sp, 4
sw ra, 0(sp)
jal fail
lw ra, 0(sp)
la t0, restore_st
jr t0, 0
.section .text
.type trap_m_ecall, @function
trap_m_ecall:
addi sp, sp, -4
sw ra, 0(sp)
# select which system call based on a7.
# for this example we will just define the following.
# not standard with linux or anything.
# 0: execute a call back function
# 1: decrease privilege by 1 (m=>s, s=>u, u=>u)
# 2: increase privilege by 1 (m=>m, s=>m, u=>s)
# check a7
li t0, 1
beq a7, t0, trap_m_decrease_privilege
li t0, 2
beq a7, t0, trap_m_increase_privilege
# call call back function if not zero
la t1, isr_m_ecall_cb_fp
lw t0, 0(t1)
beq t0, x0, trap_m_ecall_skip_cb
jalr ra, t0, 0
trap_m_ecall_skip_cb:
# modify the mepc
csrrw t0, mepc, x0
addi t0, t0, 4
csrrw x0, mepc, t0
lw ra, 0(sp)
addi sp, sp, 4
la t0, restore_st
jr t0, 0
trap_m_decrease_privilege:
# read the mstatus register
csrrw t0, mstatus, x0
# 11 => 01, and 01 => 00.
# this is accomplished by clearing bit 12 and taking the old
# bit 12 as the new bit 11.
li t3, 0x00001800
and t1, t0, t3 # isolates the bits 12 and 11.
# shift right by 1.
srli t2, t1, 1
and t2, t2, t3 # this will clear bit 10.
li t3, ~0x00001800
and t4, t0, t3
or t0, t2, t4
csrrw x0, mstatus, t0
j trap_m_ecall_skip_cb
trap_m_increase_privilege:
# read the mstatus register
csrrw t0, mstatus, x0
# 11 => 01, and 01 => 00.
# this is accomplished by setting bit 11 and taking the old
# bit 11 as the new bit 12.
li t3, 0x00000800
li t4, ~0x00000800
and t1, t0, t3
slli t2, t1, 1 # shift left by 1.
or t2, t2, t3 # bit 11 is always set.
and t1, t0, t5
or t0, t1, t2
csrrw x0, mstatus, t0
j trap_m_ecall_skip_cb
.data
exception_table:
.int trap_instr_addr_misalign
.int trap_instr_addr_misalign #trap_instr_access_fault
.int trap_instr_addr_misalign #trap_illegal_instr
.int trap_instr_addr_misalign #trap_breakpoint
.int trap_instr_addr_misalign #trap_load_addr_misalign
.int trap_instr_addr_misalign #trap_load_access_fault
.int trap_instr_addr_misalign #trap_store_addr_misalign
.int trap_instr_addr_misalign #trap_store_access_fault
.int trap_m_ecall
.int trap_m_ecall
.int restore_st
.int trap_m_ecall
.int trap_instr_addr_misalign #trap_instr_page_fault
.int trap_instr_addr_misalign #trap_load_page_fault
.int restore_st
.int trap_instr_addr_misalign #trap_store_page_fault
#.data
#interrupt_table:
.int trap_instr_addr_misalign #trap_u_software
.int trap_instr_addr_misalign #trap_s_software
.int restore_st
.int trap_instr_addr_misalign #trap_m_software
.int trap_instr_addr_misalign #trap_u_timer
.int trap_instr_addr_misalign #trap_s_timer
.int restore_st
.int trap_instr_addr_misalign #trap_m_timer
.int trap_instr_addr_misalign #trap_u_external
.int trap_instr_addr_misalign #trap_s_external
.int restore_st
.int trap_instr_addr_misalign #trap_m_external
.int restore_st
.int restore_st
.int restore_st
.int restore_st
.section .data
.global isr_m_ecall_cb_fp
isr_m_ecall_cb_fp:
.int 0

60
testsBP/crt0/start.s Normal file
View File

@ -0,0 +1,60 @@
.section .init
.global _start
.type _start, @function
_start:
# Initialize global pointer
.option push
.option norelax
1:auipc gp, %pcrel_hi(__global_pointer$)
addi gp, gp, %pcrel_lo(1b)
.option pop
li x1, 0
li x2, 0
li x4, 0
li x5, 0
li x6, 0
li x7, 0
li x8, 0
li x9, 0
li x10, 0
li x11, 0
li x12, 0
li x13, 0
li x14, 0
li x15, 0
li x16, 0
li x17, 0
li x18, 0
li x19, 0
li x20, 0
li x21, 0
li x22, 0
li x23, 0
li x24, 0
li x25, 0
li x26, 0
li x27, 0
li x28, 0
li x29, 0
li x30, 0
li x31, 0
# set the stack pointer to the top of memory
# 0x8000_0000 + 64K - 8 bytes
li sp, 0x0000FFF8
jal ra, main
jal ra, _halt
.section .text
.global _halt
.type _halt, @function
_halt:
li gp, 1
li a0, 0
ecall
j _halt

244
testsBP/linker.x Normal file
View File

@ -0,0 +1,244 @@
OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv",
"elf64-littleriscv")
OUTPUT_ARCH(riscv)
ENTRY(_start)
SEARCH_DIR("/opt/riscv/riscv64-unknown-elf/lib");
SECTIONS
{
/* Read-only sections, merged into text segment: */
/* init segment to ensure we get a consistent start routine*/
. = 0x0000000000000000;
. = ALIGN(0x0);
.init : {
*(.init)
}
_start_end = .;
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x0)); . = SEGMENT_START("text-segment", _start_end);
.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.dyn :
{
*(.rela.init)
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
*(.rela.fini)
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
*(.rela.ctors)
*(.rela.dtors)
*(.rela.got)
*(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*)
*(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*)
*(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*)
*(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*)
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
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) }
.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.*)
/* .gnu.warning sections are handled specially by elf64.em. */
*(.gnu.warning)
}
.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*) }
/* 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*) }
/* Thread Local Storage sections */
.tdata :
{
PROVIDE_HIDDEN (__tdata_start = .);
*(.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_BEGIN__ = .;
*(.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 :
{
__SDATA_BEGIN__ = .;
*(.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 do not
pad the .data section. */
. = ALIGN(. != 0 ? 64 / 8 : 1);
}
. = ALIGN(64 / 8);
. = SEGMENT_START("ldata-segment", .);
. = ALIGN(64 / 8);
__BSS_END__ = .;
__global_pointer$ = MIN(__SDATA_BEGIN__ + 0x800,
MAX(__DATA_BEGIN__ + 0x800, __BSS_END__ - 0x800));
_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) }
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
/* 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_*) }
}

92
testsBP/makefile.inc Normal file
View File

@ -0,0 +1,92 @@
CEXT := c
CPPEXT := cpp
AEXT := s
SEXT := S
SRCEXT := \([$(CEXT)$(AEXT)$(SEXT)]\|$(CPPEXT)\)
OBJEXT := o
DEPEXT := d
SRCDIR := .
BUILDDIR := OBJ
LINKER := ${ROOT}/linker.x
SOURCES ?= $(shell find $(SRCDIR) -type f -regex ".*\.$(SRCEXT)" | sort)
OBJECTS := $(SOURCES:.$(CEXT)=.$(OBJEXT))
OBJECTS := $(OBJECTS:.$(AEXT)=.$(OBJEXT))
OBJECTS := $(OBJECTS:.$(SEXT)=.$(OBJEXT))
OBJECTS := $(OBJECTS:.$(CPPEXT)=.$(OBJEXT))
OBJECTS := $(patsubst $(SRCDIR)/%,$(BUILDDIR)/%,$(OBJECTS))
#Default Make
all: directories $(TARGET).memfile
#Remake
remake: clean all
#Make the Directories
directories:
@mkdir -p $(TARGETDIR)
@mkdir -p $(BUILDDIR)
clean:
rm -rf $(BUILDDIR) $(TARGETDIR) *.memfile *.objdump
#Needed for building additional library projects
ifdef LIBRARY_DIRS
LIBS+=${LIBRARY_DIRS:%=-L%} ${LIBRARY_FILES:%=-l%}
INC+=${LIBRARY_DIRS:%=-I%}
${LIBRARY_DIRS}:
make -C $@ -j 1
.PHONY: $(LIBRARY_DIRS) $(TARGET)
endif
#Pull in dependency info for *existing* .o files
-include $(OBJECTS:.$(OBJEXT)=.$(DEPEXT))
#Link
$(TARGET): $(OBJECTS) $(LIBRARY_DIRS)
$(CC) $(LINK_FLAGS) -g -o $(TARGET) $(OBJECTS) ${LIBS} -T ${LINKER}
#Compile
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CEXT)
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list
@$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CEXT) > $(BUILDDIR)/$*.$(DEPEXT)
@cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp
@sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT)
@sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT)
@rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp
# gcc won't output dependencies for assembly files for some reason
# most asm files don't have dependencies so the echo will work for now.
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(AEXT)
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) -c -o $@ $< > $(BUILDDIR)/$*.list
@echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT)
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(SEXT)
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list
@echo $@: $< > $(BUILDDIR)/$*.$(DEPEXT)
# C++
$(BUILDDIR)/%.$(OBJEXT): $(SRCDIR)/%.$(CPPEXT)
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(INC) -c -o $@ $< > $(BUILDDIR)/$*.list
@$(CC) $(CFLAGS) $(INC) -MM $(SRCDIR)/$*.$(CPPEXT) > $(BUILDDIR)/$*.$(DEPEXT)
@cp -f $(BUILDDIR)/$*.$(DEPEXT) $(BUILDDIR)/$*.$(DEPEXT).tmp
@sed -e 's|.*:|$(BUILDDIR)/$*.$(OBJEXT):|' < $(BUILDDIR)/$*.$(DEPEXT).tmp > $(BUILDDIR)/$*.$(DEPEXT)
@sed -e 's/.*://' -e 's/\\$$//' < $(BUILDDIR)/$*.$(DEPEXT).tmp | fmt -1 | sed -e 's/^ *//' -e 's/$$/:/' >> $(BUILDDIR)/$*.$(DEPEXT)
@rm -f $(BUILDDIR)/$*.$(DEPEXT).tmp
# convert to hex
$(TARGET).memfile: $(TARGET)
@echo 'Making object dump file.'
@riscv64-unknown-elf-objdump -D $< > $<.objdump
@echo 'Making memory file'
exe2memfile0.pl $<
extractFunctionRadix.sh $<.objdump

15
testsBP/sieve/Makefile Normal file
View File

@ -0,0 +1,15 @@
TARGETDIR := sieve
TARGET := $(TARGETDIR)/$(TARGETDIR).elf
ROOT := ..
LIBRARY_DIRS := ${ROOT}/crt0
LIBRARY_FILES := crt0
LINK_FLAGS := -nostartfiles -Wl,-Map=$(TARGET).map
CFLAGS =-march=rv64ifd -Wa,-alhs -Wa,-L -mcmodel=medany -mstrict-align
CC=riscv64-unknown-elf-gcc
DA=riscv64-unknown-elf-objdump -d
include $(ROOT)/makefile.inc

101
testsBP/sieve/sieve.c Normal file
View File

@ -0,0 +1,101 @@
/*
* Filename:
*
* sieve.c
*
* Description:
*
* The Sieve of Eratosthenes benchmark, from Byte Magazine
* early 1980s, when a PC would do well to run this in 10
* seconds. This version really does count prime numbers
* but omits the numbers 1, 3 and all even numbers. The
* expected count is 1899.
*
*/
#include <sys/time.h>
#include <stdio.h>
#define SIZE 8190
//#define SIZE 8388608
double time_diff(struct timeval x , struct timeval y);
int sieve () {
unsigned char flags [SIZE + 1];
int iter;
int count;
for (iter = 1; iter <= 10; iter++)
{
int i, prime, k;
count = 0;
for (i = 0; i <= SIZE; i++)
flags [i] = 1;
for (i = 0; i <= SIZE; i++)
{
if (flags [i])
{
prime = i + i + 3;
k = i + prime;
while (k <= SIZE)
{
flags [k] = 0;
k += prime;
}
count++;
}
}
}
return count;
}
int main () {
int ans;
struct timeval before , after;
gettimeofday(&before , NULL);
ans = sieve ();
gettimeofday(&after , NULL);
if (ans != 1899)
printf ("Sieve result wrong, ans = %d, expected 1899", ans);
printf("Total time elapsed : %.0lf us\n" , time_diff(before , after) );
printf("Round 2\n");
gettimeofday(&before , NULL);
ans = sieve ();
gettimeofday(&after , NULL);
if (ans != 1899)
printf ("Sieve result wrong, ans = %d, expected 1899", ans);
printf("Total time elapsed : %.0lf us\n" , time_diff(before , after) );
return 0;
}
double time_diff(struct timeval x , struct timeval y)
{
double x_ms , y_ms , diff;
x_ms = (double)x.tv_sec*1000000 + (double)x.tv_usec;
y_ms = (double)y.tv_sec*1000000 + (double)y.tv_usec;
diff = (double)y_ms - (double)x_ms;
return diff;
}

15
testsBP/simple/Makefile Normal file
View File

@ -0,0 +1,15 @@
TARGETDIR := simple
TARGET := $(TARGETDIR)/$(TARGETDIR).elf
ROOT := ..
LIBRARY_DIRS := ${ROOT}/crt0
LIBRARY_FILES := crt0
LINK_FLAGS := -nostartfiles -Wl,-Map=$(TARGET).map
CFLAGS =-march=rv64ifd -Wa,-alhs -Wa,-L -mcmodel=medany -mstrict-align
CC=riscv64-unknown-elf-gcc
DA=riscv64-unknown-elf-objdump -d
include $(ROOT)/makefile.inc

11
testsBP/simple/fail.s Normal file
View File

@ -0,0 +1,11 @@
# Ross Thompson
# March 17, 2021
# Oklahoma State University
.section .text
.global fail
.type fail, @function
fail:
li gp, 1
li a0, -1
ecall

6
testsBP/simple/header.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef __header
#define __header
int fail();
int simple_csrbr_test();
#endif

10
testsBP/simple/main.c Normal file
View File

@ -0,0 +1,10 @@
#include "header.h"
int main(){
int res = simple_csrbr_test();
if (res < 0) {
fail();
return 0;
}else
return 0;
}

52
testsBP/simple/sample.s Normal file
View File

@ -0,0 +1,52 @@
.section .text
.global simple_csrbr_test
.type simple_csrbr_test, @function
simple_csrbr_test:
# step 1 enable the performance counters
# by default the hardware enables all performance counters
# however we will eventually want to manually enable incase
# some other code disables thems
# step 2 read performance counters into general purpose registers
csrrw t2, 0xB05, x0 # t2 = BR COUNT (perf count 5)
csrrw t3, 0xB04, x0 # t3 = BRMP COUNT (perf count 4)
# step 3 simple loop to show the counters are updated.
li t0, 0 # this is the loop counter
li t1, 100 # this is the loop end condition
# for(t1 = 0; t1 < t0; t1++);
loop:
addi t0, t0, 1
blt t0, t1, loop
loop_done:
# step 2 read performance counters into general purpose registers
csrrw t4, 0xB05, x0 # t4 = BR COUNT (perf count 5)
csrrw t5, 0xB04, x0 # t5 = BRMP COUNT (perf count 4)
sub t2, t4, t2 # this is the number of branch instructions committed.
sub t3, t5, t3 # this is the number of branch mispredictions committed.
# now check if the branch count equals 100 and if the branch
bne t4, t2, fail
# *** come back to t3
pass:
li a0, 0
ret
fail:
li a0, -1
ret
.data
sample_data:
.int 0

View File

@ -49,6 +49,7 @@ for(my $i=0; $i<=$#ARGV; $i++) {
}
while(<FILE>) {
# *** this mode stuff does not work if a section is missing or reordered.
if ($mode == 0) { # Parse code
# print("Examining $_\n");
if (/^\s*(\S{1,16}):\s+(\S+)\s+/) {

View File

@ -316,7 +316,7 @@ string tests32i[] = {
};
string testsBP64[] = '{
"rv64BP/reg-test", "10000",
"rv64BP/simple", "10000",
"rv64BP/sieve", "1000000"
};
string tests[];