// This is free and unencumbered software released into the public domain. // // Anyone is free to copy, modify, publish, use, compile, sell, or // distribute this software, either in source code form or as a compiled // binary, for any purpose, commercial or non-commercial, and by any // means. #define ENABLE_QREGS #define ENABLE_HELLO #define ENABLE_RVTST #define ENABLE_SIEVE #define ENABLE_MULTST #define ENABLE_STATS #ifndef ENABLE_QREGS # undef ENABLE_RVTST #endif // Only save registers in IRQ wrapper that are to be saved by the caller in // the RISC-V ABI, with the excpetion of the stack pointer. The IRQ handler // will save the rest if necessary. I.e. skip x3, x4, x8, x9, and x18-x27. #undef ENABLE_FASTIRQ #include "custom_ops.S" .section .text .global irq .global hello .global sieve .global multest .global hard_mul .global hard_mulh .global hard_mulhsu .global hard_mulhu .global hard_div .global hard_divu .global hard_rem .global hard_remu .global stats reset_vec: // no more than 16 bytes here ! picorv32_waitirq_insn(zero) picorv32_maskirq_insn(zero, zero) j start /* Interrupt handler **********************************/ .balign 16 irq_vec: /* save registers */ #ifdef ENABLE_QREGS picorv32_setq_insn(q2, x1) picorv32_setq_insn(q3, x2) lui x1, %hi(irq_regs) addi x1, x1, %lo(irq_regs) picorv32_getq_insn(x2, q0) sw x2, 0*4(x1) picorv32_getq_insn(x2, q2) sw x2, 1*4(x1) picorv32_getq_insn(x2, q3) sw x2, 2*4(x1) #ifdef ENABLE_FASTIRQ sw x5, 5*4(x1) sw x6, 6*4(x1) sw x7, 7*4(x1) sw x10, 10*4(x1) sw x11, 11*4(x1) sw x12, 12*4(x1) sw x13, 13*4(x1) sw x14, 14*4(x1) sw x15, 15*4(x1) sw x16, 16*4(x1) sw x17, 17*4(x1) sw x28, 28*4(x1) sw x29, 29*4(x1) sw x30, 30*4(x1) sw x31, 31*4(x1) #else sw x3, 3*4(x1) sw x4, 4*4(x1) sw x5, 5*4(x1) sw x6, 6*4(x1) sw x7, 7*4(x1) sw x8, 8*4(x1) sw x9, 9*4(x1) sw x10, 10*4(x1) sw x11, 11*4(x1) sw x12, 12*4(x1) sw x13, 13*4(x1) sw x14, 14*4(x1) sw x15, 15*4(x1) sw x16, 16*4(x1) sw x17, 17*4(x1) sw x18, 18*4(x1) sw x19, 19*4(x1) sw x20, 20*4(x1) sw x21, 21*4(x1) sw x22, 22*4(x1) sw x23, 23*4(x1) sw x24, 24*4(x1) sw x25, 25*4(x1) sw x26, 26*4(x1) sw x27, 27*4(x1) sw x28, 28*4(x1) sw x29, 29*4(x1) sw x30, 30*4(x1) sw x31, 31*4(x1) #endif #else // ENABLE_QREGS #ifdef ENABLE_FASTIRQ sw gp, 0*4+0x200(zero) sw x1, 1*4+0x200(zero) sw x2, 2*4+0x200(zero) sw x5, 5*4+0x200(zero) sw x6, 6*4+0x200(zero) sw x7, 7*4+0x200(zero) sw x10, 10*4+0x200(zero) sw x11, 11*4+0x200(zero) sw x12, 12*4+0x200(zero) sw x13, 13*4+0x200(zero) sw x14, 14*4+0x200(zero) sw x15, 15*4+0x200(zero) sw x16, 16*4+0x200(zero) sw x17, 17*4+0x200(zero) sw x28, 28*4+0x200(zero) sw x29, 29*4+0x200(zero) sw x30, 30*4+0x200(zero) sw x31, 31*4+0x200(zero) #else sw gp, 0*4+0x200(zero) sw x1, 1*4+0x200(zero) sw x2, 2*4+0x200(zero) sw x3, 3*4+0x200(zero) sw x4, 4*4+0x200(zero) sw x5, 5*4+0x200(zero) sw x6, 6*4+0x200(zero) sw x7, 7*4+0x200(zero) sw x8, 8*4+0x200(zero) sw x9, 9*4+0x200(zero) sw x10, 10*4+0x200(zero) sw x11, 11*4+0x200(zero) sw x12, 12*4+0x200(zero) sw x13, 13*4+0x200(zero) sw x14, 14*4+0x200(zero) sw x15, 15*4+0x200(zero) sw x16, 16*4+0x200(zero) sw x17, 17*4+0x200(zero) sw x18, 18*4+0x200(zero) sw x19, 19*4+0x200(zero) sw x20, 20*4+0x200(zero) sw x21, 21*4+0x200(zero) sw x22, 22*4+0x200(zero) sw x23, 23*4+0x200(zero) sw x24, 24*4+0x200(zero) sw x25, 25*4+0x200(zero) sw x26, 26*4+0x200(zero) sw x27, 27*4+0x200(zero) sw x28, 28*4+0x200(zero) sw x29, 29*4+0x200(zero) sw x30, 30*4+0x200(zero) sw x31, 31*4+0x200(zero) #endif #endif // ENABLE_QREGS /* call interrupt handler C function */ lui sp, %hi(irq_stack) addi sp, sp, %lo(irq_stack) // arg0 = address of regs lui a0, %hi(irq_regs) addi a0, a0, %lo(irq_regs) // arg1 = interrupt type #ifdef ENABLE_QREGS picorv32_getq_insn(a1, q1) #else addi a1, tp, 0 #endif // call to C function jal ra, irq /* restore registers */ #ifdef ENABLE_QREGS // new irq_regs address returned from C code in a0 addi x1, a0, 0 lw x2, 0*4(x1) picorv32_setq_insn(q0, x2) lw x2, 1*4(x1) picorv32_setq_insn(q1, x2) lw x2, 2*4(x1) picorv32_setq_insn(q2, x2) #ifdef ENABLE_FASTIRQ lw x5, 5*4(x1) lw x6, 6*4(x1) lw x7, 7*4(x1) lw x10, 10*4(x1) lw x11, 11*4(x1) lw x12, 12*4(x1) lw x13, 13*4(x1) lw x14, 14*4(x1) lw x15, 15*4(x1) lw x16, 16*4(x1) lw x17, 17*4(x1) lw x28, 28*4(x1) lw x29, 29*4(x1) lw x30, 30*4(x1) lw x31, 31*4(x1) #else lw x3, 3*4(x1) lw x4, 4*4(x1) lw x5, 5*4(x1) lw x6, 6*4(x1) lw x7, 7*4(x1) lw x8, 8*4(x1) lw x9, 9*4(x1) lw x10, 10*4(x1) lw x11, 11*4(x1) lw x12, 12*4(x1) lw x13, 13*4(x1) lw x14, 14*4(x1) lw x15, 15*4(x1) lw x16, 16*4(x1) lw x17, 17*4(x1) lw x18, 18*4(x1) lw x19, 19*4(x1) lw x20, 20*4(x1) lw x21, 21*4(x1) lw x22, 22*4(x1) lw x23, 23*4(x1) lw x24, 24*4(x1) lw x25, 25*4(x1) lw x26, 26*4(x1) lw x27, 27*4(x1) lw x28, 28*4(x1) lw x29, 29*4(x1) lw x30, 30*4(x1) lw x31, 31*4(x1) #endif picorv32_getq_insn(x1, q1) picorv32_getq_insn(x2, q2) #else // ENABLE_QREGS // new irq_regs address returned from C code in a0 addi a1, zero, 0x200 beq a0, a1, 1f ebreak 1: #ifdef ENABLE_FASTIRQ lw gp, 0*4+0x200(zero) lw x1, 1*4+0x200(zero) lw x2, 2*4+0x200(zero) lw x5, 5*4+0x200(zero) lw x6, 6*4+0x200(zero) lw x7, 7*4+0x200(zero) lw x10, 10*4+0x200(zero) lw x11, 11*4+0x200(zero) lw x12, 12*4+0x200(zero) lw x13, 13*4+0x200(zero) lw x14, 14*4+0x200(zero) lw x15, 15*4+0x200(zero) lw x16, 16*4+0x200(zero) lw x17, 17*4+0x200(zero) lw x28, 28*4+0x200(zero) lw x29, 29*4+0x200(zero) lw x30, 30*4+0x200(zero) lw x31, 31*4+0x200(zero) #else lw gp, 0*4+0x200(zero) lw x1, 1*4+0x200(zero) lw x2, 2*4+0x200(zero) // do not restore x3 (gp) lw x4, 4*4+0x200(zero) lw x5, 5*4+0x200(zero) lw x6, 6*4+0x200(zero) lw x7, 7*4+0x200(zero) lw x8, 8*4+0x200(zero) lw x9, 9*4+0x200(zero) lw x10, 10*4+0x200(zero) lw x11, 11*4+0x200(zero) lw x12, 12*4+0x200(zero) lw x13, 13*4+0x200(zero) lw x14, 14*4+0x200(zero) lw x15, 15*4+0x200(zero) lw x16, 16*4+0x200(zero) lw x17, 17*4+0x200(zero) lw x18, 18*4+0x200(zero) lw x19, 19*4+0x200(zero) lw x20, 20*4+0x200(zero) lw x21, 21*4+0x200(zero) lw x22, 22*4+0x200(zero) lw x23, 23*4+0x200(zero) lw x24, 24*4+0x200(zero) lw x25, 25*4+0x200(zero) lw x26, 26*4+0x200(zero) lw x27, 27*4+0x200(zero) lw x28, 28*4+0x200(zero) lw x29, 29*4+0x200(zero) lw x30, 30*4+0x200(zero) lw x31, 31*4+0x200(zero) #endif #endif // ENABLE_QREGS picorv32_retirq_insn() .balign 0x200 irq_regs: // registers are saved to this memory region during interrupt handling // the program counter is saved as register 0 .fill 32,4 // stack for the interrupt handler .fill 128,4 irq_stack: /* Main program **********************************/ start: /* zero-initialize all registers */ addi x1, zero, 0 addi x2, zero, 0 addi x3, zero, 0 addi x4, zero, 0 addi x5, zero, 0 addi x6, zero, 0 addi x7, zero, 0 addi x8, zero, 0 addi x9, zero, 0 addi x10, zero, 0 addi x11, zero, 0 addi x12, zero, 0 addi x13, zero, 0 addi x14, zero, 0 addi x15, zero, 0 addi x16, zero, 0 addi x17, zero, 0 addi x18, zero, 0 addi x19, zero, 0 addi x20, zero, 0 addi x21, zero, 0 addi x22, zero, 0 addi x23, zero, 0 addi x24, zero, 0 addi x25, zero, 0 addi x26, zero, 0 addi x27, zero, 0 addi x28, zero, 0 addi x29, zero, 0 addi x30, zero, 0 addi x31, zero, 0 #ifdef ENABLE_HELLO /* set stack pointer */ lui sp,(64*1024)>>12 /* call hello C code */ jal ra,hello #endif /* running tests from riscv-tests */ #ifdef ENABLE_RVTST # define TEST(n) \ .global n; \ addi x1, zero, 1000; \ picorv32_timer_insn(zero, x1); \ jal zero,n; \ .global n ## _ret; \ n ## _ret: #else # define TEST(n) \ .global n ## _ret; \ n ## _ret: #endif TEST(lui) TEST(auipc) TEST(j) TEST(jal) TEST(jalr) TEST(beq) TEST(bne) TEST(blt) TEST(bge) TEST(bltu) TEST(bgeu) TEST(lb) TEST(lh) TEST(lw) TEST(lbu) TEST(lhu) TEST(sb) TEST(sh) TEST(sw) TEST(addi) TEST(slti) // also tests sltiu TEST(xori) TEST(ori) TEST(andi) TEST(slli) TEST(srli) TEST(srai) TEST(add) TEST(sub) TEST(sll) TEST(slt) // what is with sltu ? TEST(xor) TEST(srl) TEST(sra) TEST(or) TEST(and) TEST(mulh) TEST(mulhsu) TEST(mulhu) TEST(mul) TEST(div) TEST(divu) TEST(rem) TEST(remu) TEST(simple) /* set stack pointer */ lui sp,(64*1024)>>12 /* set gp and tp */ lui gp, %hi(0xdeadbeef) addi gp, gp, %lo(0xdeadbeef) addi tp, gp, 0 #ifdef ENABLE_SIEVE /* call sieve C code */ jal ra,sieve #endif #ifdef ENABLE_MULTST /* call multest C code */ jal ra,multest #endif #ifdef ENABLE_STATS /* call stats C code */ jal ra,stats #endif /* print "DONE\n" */ lui a0,0x10000000>>12 addi a1,zero,'D' addi a2,zero,'O' addi a3,zero,'N' addi a4,zero,'E' addi a5,zero,'\n' sw a1,0(a0) sw a2,0(a0) sw a3,0(a0) sw a4,0(a0) sw a5,0(a0) li a0, 0x20000000 li a1, 123456789 sw a1,0(a0) /* trap */ ebreak /* Hard mul functions for multest.c **********************************/ hard_mul: mul a0, a0, a1 ret hard_mulh: mulh a0, a0, a1 ret hard_mulhsu: mulhsu a0, a0, a1 ret hard_mulhu: mulhu a0, a0, a1 ret hard_div: div a0, a0, a1 ret hard_divu: divu a0, a0, a1 ret hard_rem: rem a0, a0, a1 ret hard_remu: remu a0, a0, a1 ret