Files
c_soft/riscv_cpu/riscv.c

828 lines
21 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "riscv.h"
#include "debug.h"
#include "stdio.h"
#include "stdlib.h"
#include "errno.h"
#include "string.h"
#include "../main.h"
#define device_write(riscv,addr,value) \
for (int i = 0;i < riscv->device_num;i++) {\
if (riscv->device_list[i] && riscv->device_list[i]->write) {\
if(addr>=riscv->device_list[i]->addr && addr<riscv->device_list[i]->addr+riscv->device_list[i]->size) {\
riscv->device_list[i]->write(addr, value);\
return;\
}\
}\
}
#define device_read(riscv,addr,ret) \
for (int i = 0;i < riscv->device_num;i++) {\
if (riscv->device_list[i] && riscv->device_list[i]->read) {\
if(addr>=riscv->device_list[i]->addr && addr<riscv->device_list[i]->addr+riscv->device_list[i]->size) {\
ret=riscv->device_list[i]->read(addr);\
return ret;\
}\
}\
}
int riscv_print(riscv_t* riscv) {
printf("x0(zero): %08x\n", riscv->zero);
printf("x1(ra): %08x\n", riscv->ra);
printf("x2(sp): %08x\n", riscv->sp);
printf("x3(gp): %08x\n", riscv->gp);
printf("x4(tp): %08x\n", riscv->tp);
printf("x5(t0): %08x\n", riscv->t0);
printf("x6(t1): %08x\n", riscv->t1);
printf("x7(t2): %08x\n", riscv->t2);
printf("x8(s0|fp): %08x\n", riscv->fp);
printf("x9(s1): %08x\n", riscv->s1);
printf("x10(a0): %08x\n", riscv->a0);
printf("x11(a1): %08x\n", riscv->a1);
printf("x12(a2): %08x\n", riscv->a2);
printf("x13(a3): %08x\n", riscv->a3);
printf("x14(a4): %08x\n", riscv->a4);
printf("x15(a5): %08x\n", riscv->a5);
printf("x16(a6): %08x\n", riscv->a6);
printf("x17(a7): %08x\n", riscv->a7);
printf("x18(s2): %08x\n", riscv->s2);
printf("x19(s3): %08x\n", riscv->s3);
printf("x20(s4): %08x\n", riscv->s4);
printf("x21(s5): %08x\n", riscv->s5);
printf("x22(s6): %08x\n", riscv->s6);
printf("x23(s7): %08x\n", riscv->s7);
printf("x24(s8): %08x\n", riscv->s8);
printf("x25(s9): %08x\n", riscv->s9);
printf("x26(s10): %08x\n", riscv->s10);
printf("x27(s11): %08x\n", riscv->s11);
printf("x28(t3): %08x\n", riscv->t3);
printf("x29(t4): %08x\n", riscv->t4);
printf("x30(t5): %08x\n", riscv->t5);
printf("x31(t6): %08x\n", riscv->t6);
return 0;
}
void mem_w_write(riscv_t * riscv, uint32_t addr, uint32_t value) {
if (addr & 0x3) {
riscv->exc_code = 6;
riscv->mtval = addr;
return;
}
if (addr >= MEM_ADDR_BASE && addr < MEM_ADDR_BASE + MEM_SIZE) {
mem_wr(addr) = value;
} else {
device_write(riscv, addr, value);
riscv->exc_code = 7;
riscv->mtval = addr;
}
}
void mem_wh_write(riscv_t* riscv, uint32_t addr, uint16_t value) {
if (addr & 0x1) {
riscv->exc_code = 6;
riscv->mtval = addr;
return;
}
if (addr >= MEM_ADDR_BASE && addr < MEM_ADDR_BASE + MEM_SIZE) {
mem_wrh(addr) = value;
} else {
device_write(riscv, addr, value);
riscv->exc_code = 7;
riscv->mtval = addr;
}
}
void mem_wb_write(riscv_t* riscv, uint32_t addr, uint8_t value) {
if (addr >= MEM_ADDR_BASE && addr < MEM_ADDR_BASE + MEM_SIZE) {
mem_wrb(addr) = value;
} else {
device_write(riscv, addr, value);
riscv->exc_code = 7;
riscv->mtval = addr;
}
}
uint32_t mem_w_read(riscv_t* riscv, uint32_t addr) {
uint32_t ret = 0xaaaaaaaa;
if (addr & 0x3) {
riscv->exc_code = 4;
riscv->mtval = addr;
printf("unaligned access addr:%08x\n", addr);
return ret;
}
if (addr >= MEM_ADDR_BASE && addr < MEM_ADDR_BASE + MEM_SIZE) {
ret = mem_wr(addr);
} else if (addr>=riscv->rom_addr_base && addr<riscv->rom_addr_base+riscv->rom_size){
ret = rom_wr(addr);
} else {
device_read(riscv, addr, ret);
riscv->exc_code = 5;
riscv->mtval = addr;
printf("error addr:%08x\n", addr);
}
return ret;
}
uint16_t mem_wh_read(riscv_t* riscv, uint32_t addr) {
uint16_t ret = 0xaaaa;
if (addr & 0x1) {
riscv->exc_code = 4;
riscv->mtval = addr;
return ret;
}
if (addr >= MEM_ADDR_BASE && addr < MEM_ADDR_BASE + MEM_SIZE) {
ret = mem_wrh(addr);
} else if (addr>=riscv->rom_addr_base && addr<riscv->rom_addr_base+riscv->rom_size){
ret = rom_wrh(addr);
} else {
device_read(riscv, addr, ret);
riscv->exc_code = 5;
riscv->mtval = addr;
}
return ret;
}
uint8_t mem_wb_read(riscv_t* riscv, uint32_t addr) {
uint8_t ret = 0xaa;
// printf("read addr=%08x\n", addr);
if (addr >= MEM_ADDR_BASE && addr < MEM_ADDR_BASE + MEM_SIZE) {
ret = mem_wrb(addr);
} else if (addr>=riscv->rom_addr_base && addr<riscv->rom_addr_base+riscv->rom_size){
ret = rom_wrb(addr);
} else {
device_read(riscv, addr, ret);
riscv->exc_code = 5;
riscv->mtval = addr;
}
return ret;
}
void ins_add(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = riscv->reg[rs1] + riscv->reg[rs2];
}
void ins_addi(riscv_t* riscv, int rs1, int imm, int rd) {
riscv->reg[rd] = (int)riscv->reg[rs1] + imm;
}
void ins_addiw(riscv_t* riscv, int rs1, int imm, int rd) {
riscv->reg[rd] = riscv->reg[rs1] + imm;
}
void ins_addw(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = riscv->reg[rs1] + riscv->reg[rs2];
}
void ins_and(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = riscv->reg[rs1] & riscv->reg[rs2];
}
void ins_andi(riscv_t* riscv, int rs1, int imm, int rd) {
riscv->reg[rd] = riscv->reg[rs1] & imm;
}
// 设置pc指针高位地址
void ins_auipc(riscv_t* riscv, int imm, int rd) {
riscv->reg[rd] = riscv->pc + imm;
}
void ins_beq(riscv_t* riscv, int rs2, int rs1, int imm) {
if (riscv->reg[rs1] == riscv->reg[rs2]) {
riscv->pc += imm;
riscv->pc_modify = 1;
}
}
void ins_bge(riscv_t* riscv, int rs2, int rs1, int imm) {
if ((int)riscv->reg[rs1] >= (int)riscv->reg[rs2]) {
riscv->pc += imm;
riscv->pc_modify = 1;
}
}
void ins_bgeu(riscv_t* riscv, int rs2, int rs1, int imm) {
if (riscv->reg[rs1] >= riscv->reg[rs2]) {
riscv->pc += imm;
riscv->pc_modify = 1;
}
}
void ins_blt(riscv_t* riscv, int rs2, int rs1, int imm) {
if ((int)riscv->reg[rs1] < (int)riscv->reg[rs2]) {
riscv->pc += imm;
riscv->pc_modify = 1;
}
}
void ins_bltu(riscv_t* riscv, int rs2, int rs1, int imm) {
if (riscv->reg[rs1] < riscv->reg[rs2]) {
riscv->pc += imm;
riscv->pc_modify = 1;
}
}
void ins_bne(riscv_t* riscv, int rs2, int rs1, int imm) {
// printf("bne %d %d imm=%08x\n", rs2, rs1, imm);
if (riscv->reg[rs1] != riscv->reg[rs2]) {
riscv->pc += imm;
riscv->pc_modify = 1;
}
}
// 读后清除
void ins_csrrc(riscv_t* riscv, int rs1, int rd, int csr) {
uint32_t t = riscv->csrs[csr];
riscv->csrs[csr] = riscv->csrs[csr] & ~riscv->reg[rs1];
riscv->reg[rd] = t;
}
void ins_csrrs(riscv_t* riscv, int rs1, int rd, int csr) {
uint32_t t = riscv->csrs[csr];
riscv->csrs[csr] = riscv->csrs[csr] | riscv->reg[rs1];
riscv->reg[rd] = t;
}
void ins_csrrw(riscv_t* riscv, int rs1, int rd, int csr) {
uint32_t t = riscv->csrs[csr];
riscv->csrs[csr] = riscv->reg[rs1];
riscv->reg[rd] = t;
}
void ins_csrrci(riscv_t* riscv, int imm, int rd, int csr) {
uint32_t t = riscv->csrs[csr];
riscv->csrs[csr] = riscv->csrs[csr] & ~imm;
riscv->reg[rd] = t;
}
void ins_csrrsi(riscv_t* riscv, int imm, int rd, int csr) {
uint32_t t = riscv->csrs[csr];
riscv->csrs[csr] = riscv->csrs[csr] | imm;
riscv->reg[rd] = t;
}
void ins_csrrwi(riscv_t* riscv, int imm, int rd, int csr) {
uint32_t t = riscv->csrs[csr];
riscv->csrs[csr] = imm;
riscv->reg[rd] = t;
}
void ins_ecall(riscv_t* riscv) {
printf("ecall\n");
}
void ins_ebreak(riscv_t* riscv) {
printf("ebreak\n");
}
void ins_jal(riscv_t* riscv, int imm, int rd) {
riscv->reg[rd] = riscv->pc + 4;
riscv->pc += imm;
riscv->pc_modify = 1;
}
void ins_jalr(riscv_t* riscv, int rs1, int imm, int rd) {
uint32_t t;
t = riscv->pc + 4;
riscv->pc = (riscv->reg[rs1] + imm) & (~1);
riscv->reg[rd] = t;
riscv->pc_modify = 1;
}
void ins_lb(riscv_t* riscv, int rs1, int imm, int rd) {
uint32_t addr = riscv->reg[rs1] + imm;
// printf("lb %08x,imm=%d\n",addr,imm);
uint32_t r=mem_wb_read(riscv, addr);
if(r&(0x80)){
r|=0xffffff00;
}
riscv->reg[rd] = r;
}
void ins_lbu(riscv_t* riscv, int rs1, int imm, int rd) {
uint32_t addr = riscv->reg[rs1] + imm;
// printf("lbu %08x,imm=%d\n",addr,imm);
riscv->reg[rd] = mem_wb_read(riscv, addr);
}
void ins_lh(riscv_t* riscv, int rs1, int imm, int rd) {
uint32_t addr = riscv->reg[rs1] + imm;
// printf("lh %08x,imm=%d\n",addr,imm);
uint32_t r=mem_wh_read(riscv, addr);
if(r&(0x8000)){
r|=0xffff0000;
}
riscv->reg[rd] = r;
}
void ins_lhu(riscv_t* riscv, int rs1, int imm, int rd) {
uint32_t addr = riscv->reg[rs1] + imm;
// printf("lhu %08x,imm=%d\n",addr,imm);
riscv->reg[rd] = mem_wh_read(riscv, addr);
}
void ins_lw(riscv_t* riscv, int rs1, int imm, int rd) {
uint32_t addr = riscv->reg[rs1] + imm;
// printf("lw %08x,imm=%d\n",addr,imm);
riscv->reg[rd] = (int)mem_w_read(riscv, addr);
}
void ins_lwu(riscv_t* riscv, int rs1, int imm, int rd) {
uint32_t addr = riscv->reg[rs1] + imm;
// printf("lwu %08x,imm=%d\n",addr,imm);
riscv->reg[rd] = mem_w_read(riscv, addr);
}
void ins_lui(riscv_t* riscv, int imm, int rd) {
riscv->reg[rd] = imm;
}
void ins_mret(riscv_t* riscv) {
riscv->pc = riscv->mepc;
riscv->pc_modify = 1;
if (riscv->mstatus & MSTATUS_MPIE) {
riscv->mstatus &= ~MSTATUS_MPIE;
riscv->mstatus |= MSTATUS_MIE;
} else {
riscv->mstatus &= ~MSTATUS_MIE;
}
// printf("mret: pc=%08x\n", riscv->pc);
}
void ins_or(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = riscv->reg[rs1] | riscv->reg[rs2];
}
void ins_ori(riscv_t* riscv, int rs1, int imm, int rd) {
riscv->reg[rd] = riscv->reg[rs1] | imm;
}
void ins_sb(riscv_t* riscv, int rs2, int rs1, int imm) {
uint32_t addr = riscv->reg[rs1] + imm;
// printf("sb %08x,imm=%d\n",addr,imm);
mem_wb_write(riscv, addr, riscv->reg[rs2]);
}
void ins_sh(riscv_t* riscv, int rs2, int rs1, int imm) {
uint32_t addr = riscv->reg[rs1] + imm;
// printf("sh %08x,imm=%d\n",addr,imm);
mem_wh_write(riscv, addr, riscv->reg[rs2]);
}
void ins_sw(riscv_t* riscv, int rs2, int rs1, int imm) {
uint32_t addr = riscv->reg[rs1] + imm;
// printf("sw %08x,imm=%d\n",addr,imm);
mem_w_write(riscv, addr, riscv->reg[rs2]);
}
void ins_sll(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = riscv->reg[rs1] << riscv->reg[rs2];
}
void ins_slli(riscv_t* riscv, int rs1, int imm, int rd) {
riscv->reg[rd] = riscv->reg[rs1] << imm;
}
void ins_slliw(riscv_t* riscv, int rs1, int imm, int rd) {
riscv->reg[rd] = riscv->reg[rs1] << imm;
}
void ins_sllw(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = riscv->reg[rs1] << riscv->reg[rs2];
}
void ins_slt(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = (int)riscv->reg[rs1] < (int)riscv->reg[rs2];
}
void ins_slti(riscv_t* riscv, int rs1, int imm, int rd) {
riscv->reg[rd] = (int)riscv->reg[rs1] < imm;
}
void ins_sltiu(riscv_t* riscv, int rs1, int imm, int rd) {
riscv->reg[rd] = riscv->reg[rs1] < (uint32_t)imm;
}
void ins_sltu(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = riscv->reg[rs1] < riscv->reg[rs2];
}
void ins_sra(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = (int)riscv->reg[rs1] >> riscv->reg[rs2];
}
void ins_srai(riscv_t* riscv, int rs1, int imm, int rd) {
riscv->reg[rd] = (int)riscv->reg[rs1] >> imm;
}
void ins_sraiw(riscv_t* riscv, int rs1, int imm, int rd) {
riscv->reg[rd] = (int)riscv->reg[rs1] >> imm;
}
void ins_sraw(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = (int)riscv->reg[rs1] >> riscv->reg[rs2];
}
void ins_srl(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = riscv->reg[rs1] >> riscv->reg[rs2];
}
void ins_srli(riscv_t* riscv, int rs1, int imm, int rd) {
riscv->reg[rd] = riscv->reg[rs1] >> imm;
}
void ins_srliw(riscv_t* riscv, int rs1, int imm, int rd) {
riscv->reg[rd] = riscv->reg[rs1] >> imm;
}
void ins_srlw(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = riscv->reg[rs1] >> riscv->reg[rs2];
}
void ins_sub(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = riscv->reg[rs1] - riscv->reg[rs2];
}
void ins_subw(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = riscv->reg[rs1] - riscv->reg[rs2];
}
void ins_wfi(riscv_t* riscv) {
printf("wfi\n");
}
void ins_xor(riscv_t* riscv, int rs2, int rs1, int rd) {
riscv->reg[rd] = riscv->reg[rs1] ^ riscv->reg[rs2];
}
void ins_xori(riscv_t* riscv, int rs1, int imm, int rd) {
riscv->reg[rd] = riscv->reg[rs1] ^ imm;
}
// 解析指令
int riscv_decode(riscv_t* riscv, uint32_t ins) {
int imm = 0;
int rs1 = (ins >> 15) & 0x1f;
int rs2 = (ins >> 20) & 0x1f;
int rd = (ins >> 7) & 0x1f;
int funct3 = (ins >> 12) & 0x7;
int funct7 = (ins >> 25) & 0x7f;
int opcode = ins & 0x7f;
switch (opcode) {
// U-type
case opcode_lui:
imm_u_type(ins, imm);
ins_lui(riscv, imm, rd);
break;
case opcode_auipc:
imm_u_type(ins, imm);
ins_auipc(riscv, imm, rd);
break;
// J-type
case opcode_jal:
imm_j_type(ins, imm);
ins_jal(riscv, imm, rd);
break;
case opcode_jalr:
// I-type
imm_i_type(ins, imm);
ins_jalr(riscv, rs1, imm, rd);
break;
case opcode_beq:
imm_b_type(ins, imm);
switch(funct3) {
case 0x0:
ins_beq(riscv, rs2, rs1, imm);
break;
case 0x1:
ins_bne(riscv, rs2, rs1, imm);
break;
case 0x4:
ins_blt(riscv, rs2, rs1, imm);
break;
case 0x5:
ins_bge(riscv, rs2, rs1, imm);
break;
case 0x6:
ins_bltu(riscv, rs2, rs1, imm);
break;
case 0x7:
ins_bgeu(riscv, rs2, rs1, imm);
break;
default:
riscv->exc_code = 2;
break;
}
break;
case opcode_lb:
imm_i_type(ins, imm);
switch (funct3)
{
case 0x0:
ins_lb(riscv, rs1, imm, rd);
break;
case 0x1:
ins_lh(riscv, rs1, imm, rd);
break;
case 0x2:
ins_lw(riscv, rs1, imm, rd);
break;
case 0x4:
ins_lbu(riscv, rs1, imm, rd);
break;
case 0x5:
ins_lhu(riscv, rs1, imm, rd);
break;
default:
riscv->exc_code = 2;
break;
}
break;
case opcode_sb:
imm_s_type(ins, imm);
switch (funct3) {
case 0x0:
ins_sb(riscv, rs2, rs1, imm);
break;
case 0x1:
ins_sh(riscv, rs2, rs1, imm);
break;
case 0x2:
ins_sw(riscv, rs2, rs1, imm);
break;
default:
riscv->exc_code = 2;
break;
}
break;
case opcode_addi:
imm_i_type(ins,imm);
switch (funct3)
{
case 0x0:
ins_addi(riscv, rs1, imm, rd);
break;
case 0x2:
ins_slti(riscv, rs1, imm, rd);
break;
case 0x3:
ins_sltiu(riscv, rs1, imm, rd);
break;
case 0x4:
ins_xori(riscv, rs1, imm, rd);
break;
case 0x6:
ins_ori(riscv, rs1, imm, rd);
break;
case 0x7:
ins_andi(riscv, rs1, imm, rd);
break;
case 0x1:
imm = imm&0x1f;
ins_slli(riscv, rs1, imm, rd);
break;
case 0x5:
imm = imm&0x1f;
if(funct7 == 0x20){
ins_srai(riscv, rs1, imm, rd);
}else{
ins_srli(riscv, rs1, imm, rd);
}
break;
default:
riscv->exc_code = 2;
break;
}
break;
case opcode_add:
switch (funct3)
{
case 0x0:
if(funct7 == 0x20){
ins_sub(riscv, rs2, rs1, rd);
}else{
ins_add(riscv, rs2, rs1, rd);
}
break;
case 0x1:
ins_sll(riscv, rs2, rs1, rd);
break;
case 0x2:
ins_slt(riscv, rs2, rs1, rd);
break;
case 0x3:
ins_sltu(riscv, rs2, rs1, rd);
break;
case 0x4:
ins_xor(riscv, rs2, rs1, rd);
break;
case 0x5:
if (funct7 == 0x20) {
ins_sra(riscv, rs2, rs1, rd);
}else{
ins_srl(riscv, rs2, rs1, rd);
}
break;
case 0x6:
ins_or(riscv, rs2, rs1, rd);
break;
case 0x7:
ins_and(riscv, rs2, rs1, rd);
break;
default:
riscv->exc_code = 2;
break;
}
break;
case opcode_ecall:
imm_csr(ins,imm);
switch (funct3)
{
case 0x0:
if (imm == 1) {
ins_ebreak(riscv);
} else if (imm == 0) {
ins_ecall(riscv);
} else if (ins == 0x30200073) {
ins_mret(riscv);
} else{
riscv->exc_code = 2;
}
break;
case 0x1:
ins_csrrw(riscv, rs1, rd, imm);
break;
case 0x2:
ins_csrrs(riscv, rs1, rd, imm);
break;
case 0x3:
ins_csrrc(riscv, rs1, rd, imm);
break;
case 0x5:
// rs1 保存的是zimm 值
ins_csrrwi(riscv, rs1, rd, imm);
break;
case 0x6:
ins_csrrsi(riscv, rs1, rd, imm);
break;
case 0x7:
ins_csrrci(riscv, rs1, rd, imm);
break;
default:
riscv->exc_code = 2;
break;
}
break;
default:
riscv->exc_code = 2;
break;
}
if (riscv->exc_code == 2) {
riscv->mtval = ins;
}
return 0;
}
// 注册外设
int riscv_register_device(riscv_t* riscv, const device_t* device) {
if (riscv->device_num >= DEVICE_MAX_NUM) {
printf("riscv register device failed, device num out of range\n");
return -1;
}
// printf("device: base_addr=%08x, size=%08x\n", device->addr, device->size);
riscv->device_list[riscv->device_num] = device;
riscv->device_num++;
return 0;
}
// 跑外设(执行外设逻辑,设置中断等)
int riscv_device_run(riscv_t* riscv) {
for (int i = 0;i < riscv->device_num;i++) {
if (riscv->device_list[i] && riscv->device_list[i]->run) {
riscv->device_list[i]->run(riscv, riscv->device_list[i]);
}
}
return 0;
}
// 外设初始化
int riscv_device_init(riscv_t* riscv) {
for (int i = 0;i < riscv->device_num;i++) {
if (riscv->device_list[i] && riscv->device_list[i]->init) {
riscv->device_list[i]->init(riscv->device_list[i]);
}
}
return 0;
}
int riscv_init(riscv_t* riscv, uint32_t* rom, uint32_t rom_addr_base, uint32_t rom_size) {
riscv->rom = rom;
riscv->rom_size = rom_size;
riscv->rom_addr_base = rom_addr_base;
riscv->pc = riscv->rom_addr_base;
riscv->pc_modify = 0;
riscv->ra = 0xffffffff;
return 0;
}
// 进入中断 is_interrupt=1 进入中断 is_interrupt=0 进入异常
// irq_num 中断号
int riscv_enter_trap(riscv_t* riscv, int is_interrupt, int irq_num) {
riscv->mepc = riscv->pc;
riscv->mcause = (is_interrupt << 31) | irq_num;
riscv->pc = riscv->mtvec;
riscv->pc_modify = 1;
// 禁用全局中断
if (riscv->mstatus & MSTATUS_MIE) {
riscv->mstatus &= ~MSTATUS_MIE;
riscv->mstatus |= MSTATUS_MPIE;
} else {
riscv->mstatus &= ~MSTATUS_MPIE;
}
return 0;
}
// 检测是否产生了中断
int riscv_irq_check(riscv_t* riscv) {
uint32_t tmp;
int irq_num = 0;
tmp = riscv->mip & (MIP_MSIP | MIP_MTIP | MIP_MEIP);
if (tmp) {
if (riscv->mstatus & MSTATUS_MIE) {
if ((riscv->mie & MIP_MSIP) && (tmp & MIP_MSIP)) {
irq_num = 3;
} else if ((riscv->mie & MIP_MTIP) && (tmp & MIP_MTIP)) {
irq_num = 7;
} else if ((riscv->mie & MIP_MEIP) && (tmp & MIP_MEIP)) {
irq_num = 11;
}
riscv->mtval = 0;
if (irq_num>0) {
riscv_enter_trap(riscv, 1, irq_num);
riscv->mip &= ~(1 << irq_num);
irq_num = 0;
}
}
}
return 0;
}
int riscv_run(riscv_t* riscv) {
int ret = 0;
while (1) {
if (riscv->pc == 0xfffffffe && riscv->ra == 0xffffffff) {
break;
}
if (riscv->pc >= riscv->rom_addr_base + riscv->rom_size || riscv->pc < riscv->rom_addr_base) {
// 指令访问失败
riscv->mtval = riscv->pc;
// printf("riscv run out of rom pc=%08x\n",riscv->pc);
riscv_enter_trap(riscv, 0, 1);
}
if (riscv->pc & 0x3) {
// 指令地址未对齐
riscv->mtval = riscv->pc;
riscv_enter_trap(riscv, 0, 0);
}
uint32_t instr = riscv->rom[(riscv->pc - riscv->rom_addr_base) >> 2];
// printf("pc: %08x instr: %08x\n", riscv->pc, instr);
ret = riscv_decode(riscv, instr);
riscv->zero = 0;
// 如果指令修改了pc则以修改后的为准如果pc未被修改则继续执行下一条指令
if (!riscv->pc_modify) {
riscv->pc += 4;
} else {
// printf("pc modify=1\n");
riscv->pc_modify = 0;
}
if (riscv->exc_code > 0) {
riscv_enter_trap(riscv, 0, riscv->exc_code);
riscv->exc_code = 0;
}
riscv_device_run(riscv);
riscv_irq_check(riscv);
// riscv_print(riscv);
if(ret){
break;
}
if (riscv->mscratch == 0xffffffff) {
printf("proactively terminate\n");
break;
}
}
printf("riscv run end\n");
return 0;
}