try catch 不处理动态内存,拆分riscv_rest

This commit is contained in:
2025-06-24 17:59:23 +08:00
parent d9baa7f7a3
commit b64401d556
14 changed files with 115 additions and 83 deletions

827
riscv_cpu/riscv.c Normal file
View File

@@ -0,0 +1,827 @@
#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;
}