-
-
Save xobs/218adafdd1b7b3670561e845e10ee4a3 to your computer and use it in GitHub Desktop.
Demo program showing that Renode is incorrectly generating exceptions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// This program tests `ecall` and `ebreak`. Link with the | |
// following linker script: | |
// | |
//-- linker.x ---------------------------------------------- | |
// MEMORY { FLASH : ORIGIN = 0x80000000, LENGTH = 512K } | |
// SECTIONS { .text : { *(.text .text.*); } > FLASH } | |
//---------------------------------------------------------- | |
// | |
// Compile and link into a binary with: | |
// riscv-none-elf-gcc -march=rv32imac_zicsr -g my.S -o my.elf -nostdinc -nostdlib -T my.ld | |
// riscv-none-elf-objcopy -O binary my.elf my.bin | |
// | |
// Run this in tinyemu with the following configuration: | |
//-- my.cfg ------------------------------------------------ | |
// { version: 1, memory_size: 1, machine: "riscv32", bios: "my.bin", } | |
//---------------------------------------------------------- | |
// | |
// Run this in Renode with the following script: | |
//-- my.resc ----------------------------------------------- | |
// mach create | |
// using sysbus | |
// machine LoadPlatformDescriptionFromString "cpu: CPU.VexRiscv @ sysbus { cpuType: \"rv32gc\"; timeProvider: empty }" | |
// machine LoadPlatformDescriptionFromString "mem: Memory.MappedMemory @ sysbus 0x80000000 { size: 0x1000 }" | |
// machine LoadPlatformDescriptionFromString "uart: UART.LiteX_UART @ sysbus 0x40008000" | |
// sysbus LoadELF @my.elf | |
// showAnalyzer uart | |
// start | |
//---------------------------------------------------------- | |
// These values come from tinyemu, and is the HTIF offset | |
.equ UART_BASE, 0x40008000 | |
// This value needs to be written to UART_BASE+4 in order | |
// to print a character. | |
.equ CONSOLE_OUTPUT, 0x1010000 | |
.section .text | |
.globl _start | |
_start: | |
// Set up s0 and s1 for character printing | |
li s0, UART_BASE | |
li s1, CONSOLE_OUTPUT | |
// Print a character to make sure things work | |
li a0, '!' | |
jal ra, putc | |
// Print out a test string to make sure things work | |
lui a0, %hi(start_msg) | |
addi a0, a0, %lo(start_msg) | |
jal ra, puts | |
// Assign our exception handler | |
lui a0, %hi(exception_handler) | |
addi a0, a0, %lo(exception_handler) | |
csrw mtvec, a0 | |
// Set mstatus.MIE=1 (enable M mode interrupt) | |
li a0, 8 | |
csrs mstatus, a0 | |
// Set mie.MSIP=1 (enable M software interrupts) | |
li a0, 8 | |
csrs mie, a0 | |
// Perform our test | |
ecall | |
ebreak | |
ecall | |
ebreak | |
lui a0, %hi(finish_msg) | |
addi a0, a0, %lo(finish_msg) | |
jal ra, puts | |
j exit | |
.align 4 | |
exception_handler: | |
// Skip past the instruction. Note: It may be a | |
// compressed instruction (noted by the bottom two | |
// bits being 0b10) | |
csrr t0, mepc | |
lh t1, 0(t0) | |
li t2, 2 | |
andi t1, t1, 3 | |
beq t1, t2, 1f | |
addi t0, t0, 4 | |
j 2f | |
1: addi t0, t0, 2 | |
2: csrw mepc, t0 | |
csrr t0, mcause | |
li t1, 11 | |
beq t0, t1, m_ecall | |
li t1, 3 | |
beq t0, t1, m_ebreak | |
lui a0, %hi(unhandled_exception_happened_str) | |
addi a0, a0, %lo(unhandled_exception_happened_str) | |
jal ra, puts | |
j exit | |
m_ecall: | |
lui a0, %hi(m_ecall_happened_str) | |
addi a0, a0, %lo(m_ecall_happened_str) | |
jal ra, puts | |
mret | |
m_ebreak: | |
lui a0, %hi(ebreak_happened_str) | |
addi a0, a0, %lo(ebreak_happened_str) | |
jal ra, puts | |
mret | |
exit: | |
li a0, 1 | |
sw a0, 0(s0) | |
sw zero, 4(s0) | |
2: j 2b | |
putc: | |
sw a0, 0(s0) | |
sw s1, 4(s0) | |
ret | |
puts: | |
1: lbu a1, (a0) | |
beqz a1, 3f | |
sw a1, 0(s0) | |
sw s1, 4(s0) | |
addi a0, a0, 1 | |
j 1b | |
3: ret | |
start_msg: | |
.string "starting test...\n" | |
finish_msg: | |
.string "finished test\n" | |
unhandled_exception_happened_str: | |
.string "unhandled exception happened\n" | |
m_ecall_happened_str: | |
.string "ecall instruction from machine mode\n" | |
ebreak_happened_str: | |
.string "ebreak instruction\n" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment