#include "tb_cxxrtl_io.h" #include "hazard3_csr.h" /*EXPECTED-OUTPUT*************************************************************** 1: defined illegal all-zeroes Exception, mcause = 2 16-bit illegal instruction: 0000 2: defined illegal all-ones Exception, mcause = 2 32-bit illegal instruction: ffffffff 3: unimplemented CSR 0xfff Exception, mcause = 2 32-bit illegal instruction: fff027f3 4: write to read-only CSR Exception, mcause = 2 32-bit illegal instruction: f1101073 5: unimplemented instruction (F extension) Exception, mcause = 2 32-bit illegal instruction: 00052087 *******************************************************************************/ int main() { tb_puts("1: defined illegal all-zeroes\n"); asm volatile (".hword 0x0000"); tb_puts("2: defined illegal all-ones\n"); asm volatile (".word 0xffffffff"); tb_puts("3: unimplemented CSR 0xfff\n"); uint32_t junk; asm volatile ("csrr %0, 0xfff" : "=r" (junk)); tb_puts("4: write to read-only CSR\n"); asm volatile ("csrw mvendorid, zero"); // However a clear/set with zero value does not count as a write, so this // won't appear in the printf output: asm volatile ("csrs mvendorid, zero"); tb_puts("5: unimplemented instruction (F extension)\n"); asm volatile (".word 0x00052087"); // flw ft1, (a0) return 0; } void __attribute__((interrupt)) handle_exception() { uintptr_t mepc = read_csr(mepc); uint32_t mcause = read_csr(mcause); tb_printf("Exception, mcause = %u\n", mcause); uint16_t i0 = *(uint16_t*)mepc; if ((i0 & 0x3u) == 0x3u) { uint16_t i1 = *(uint16_t*)(mepc + 2); tb_printf("32-bit illegal instruction: %04x%04x\n", i1, i0); mepc += 4; } else { tb_printf("16-bit illegal instruction: %04x\n", i0); mepc += 2; } write_csr(mepc, mepc); }