diff --git a/nemu/src/isa/riscv32/inst.c b/nemu/src/isa/riscv32/inst.c index 9224f10..1dd92ab 100644 --- a/nemu/src/isa/riscv32/inst.c +++ b/nemu/src/isa/riscv32/inst.c @@ -13,6 +13,7 @@ * See the Mulan PSL v2 for more details. ***************************************************************************************/ +#include "common.h" #include "local-include/reg.h" #include #include @@ -23,7 +24,7 @@ #define Mw vaddr_write enum { - TYPE_R, TYPE_I, TYPE_U, TYPE_S, TYPE_J, + TYPE_R, TYPE_I, TYPE_U, TYPE_S, TYPE_B, TYPE_J, TYPE_N, // none }; @@ -32,7 +33,8 @@ enum { #define immI() do { *imm = SEXT(BITS(i, 31, 20), 12); } while(0) #define immU() do { *imm = SEXT(BITS(i, 31, 12), 20) << 12; } while(0) #define immS() do { *imm = (SEXT(BITS(i, 31, 25), 7) << 5) | BITS(i, 11, 7); } while(0) -#define immJ() do { *imm = (SEXT(BITS(i, 31, 30), 1) << 20) | BITS(i, 30, 21) << 1 | BITS(i, 21, 20) << 11 | BITS(i, 19, 12) << 12; } while(0) +#define immB() do { *imm = (SEXT(BITS(i, 31, 31), 1) << 12 | BITS(i, 30, 25) << 5 | BITS(i, 11, 8) << 1 | BITS(i, 8, 8) << 11; } while(0) +#define immJ() do { *imm = (SEXT(BITS(i, 31, 31), 1) << 20) | BITS(i, 30, 21) << 1 | BITS(i, 20, 20) << 11 | BITS(i, 19, 12) << 12; } while(0) static void decode_operand(Decode *s, int *rd, word_t *src1, word_t *src2, word_t *imm, int type) { uint32_t i = s->isa.inst.val; @@ -48,6 +50,12 @@ static void decode_operand(Decode *s, int *rd, word_t *src1, word_t *src2, word_ } } +static void do_branch(Decode *s, bool condition, word_t offset) { + if (condition) { + s->dnpc = s->pc + offset; + } +} + static int decode_exec(Decode *s) { int rd = 0; word_t src1 = 0, src2 = 0, imm = 0; @@ -64,10 +72,21 @@ static int decode_exec(Decode *s) { INSTPAT("??????? ????? ????? ??? ????? 00101 11", auipc , U, R(rd) = s->pc + imm); INSTPAT("??????? ????? ????? ??? ????? 11011 11", jal , J, do {s->dnpc = s->pc + imm; R(rd) = s->pc + 4; } while(0)); INSTPAT("??????? ????? ????? ??? ????? 11001 11", jalr , I, do {s->dnpc = src1 + imm; R(rd) = s->pc + 4; } while(0)); + INSTPAT("??????? ????? ????? 000 ????? 11000 11", beq , B, do_branch(s, src1 == src2, imm)); + INSTPAT("??????? ????? ????? 001 ????? 11000 11", bne , B, do_branch(s, src1 != src2, imm)); + INSTPAT("??????? ????? ????? 100 ????? 11000 11", blt , B, do_branch(s, (sword_t)src1 < (sword_t)src2, imm)); + INSTPAT("??????? ????? ????? 101 ????? 11000 11", bge , B, do_branch(s, (sword_t)src1 >= (sword_t)src2, imm)); + INSTPAT("??????? ????? ????? 110 ????? 11000 11", bltu , B, do_branch(s, src1 < src2, imm)); + INSTPAT("??????? ????? ????? 111 ????? 11000 11", bgeu , B, do_branch(s, src1 >= src2, imm)); + INSTPAT("??????? ????? ????? 000 ????? 00000 11", lb , I, R(rd) = SEXT(Mr(src1 + imm, 1), 8)); + INSTPAT("??????? ????? ????? 001 ????? 00000 11", lh , I, R(rd) = SEXT(Mr(src1 + imm, 2), 16)); + INSTPAT("??????? ????? ????? 010 ????? 00000 11", lw , I, R(rd) = SEXT(Mr(src1 + imm, 4), 32)); INSTPAT("??????? ????? ????? 100 ????? 00000 11", lbu , I, R(rd) = Mr(src1 + imm, 1)); + INSTPAT("??????? ????? ????? 101 ????? 00000 11", lhu , I, R(rd) = Mr(src1 + imm, 2)); INSTPAT("??????? ????? ????? 000 ????? 01000 11", sb , S, Mw(src1 + imm, 1, src2)); + INSTPAT("??????? ????? ????? 001 ????? 01000 11", sh , S, Mw(src1 + imm, 2, src2)); INSTPAT("??????? ????? ????? 010 ????? 01000 11", sw , S, Mw(src1 + imm, 4, src2)); - INSTPAT("??????? ????? ????? 000 ????? 00100 11", addi , I, R(rd) = src1 + (sword_t)imm); + INSTPAT("??????? ????? ????? 000 ????? 00100 11", addi , I, R(rd) = src1 + imm); INSTPAT("0000000 ????? ????? 000 ????? 01100 11", add , R, R(rd) = src1 + src2); INSTPAT("0000000 00001 00000 000 00000 11100 11", ebreak , N, NEMUTRAP(s->pc, R(10))); // R(10) is $a0