exec.c 5.7 KB
Newer Older
P
Parallels 已提交
1 2
#include "cpu/exec.h"
#include "all-instr.h"
Z
Zihao Yu 已提交
3
#include <setjmp.h>
4
#include "../intr.h"
P
Parallels 已提交
5 6

static make_EHelper(load) {
7 8 9 10 11
  static OpcodeEntry table [8] = {
    EXW(lds, 1), EXW(lds, 2), EXW(lds, 4), EXW(ld, 8), EXW(ld, 1), EXW(ld, 2), EXW(ld, 4), EMPTY
  };
  decinfo.width = table[decinfo.isa.instr.funct3].width;
  idex(pc, &table[decinfo.isa.instr.funct3]);
P
Parallels 已提交
12 13 14
}

static make_EHelper(store) {
15 16 17 18 19
  static OpcodeEntry table [8] = {
    EXW(st, 1), EXW(st, 2), EXW(st, 4), EXW(st, 8), EMPTY, EMPTY, EMPTY, EMPTY
  };
  decinfo.width = table[decinfo.isa.instr.funct3].width;
  idex(pc, &table[decinfo.isa.instr.funct3]);
P
Parallels 已提交
20 21 22
}

static make_EHelper(op_imm) {
23 24 25 26
  static OpcodeEntry table [8] = {
    EX(add), EX(sll), EX(slt), EX(sltu), EX(xor), EX(srl), EX(or), EX(and)
  };
  idex(pc, &table[decinfo.isa.instr.funct3]);
P
Parallels 已提交
27 28
}

29
static make_EHelper(op_imm32) {
30 31 32 33
  static OpcodeEntry table [8] = {
    EX(addw), EX(sllw), EMPTY, EMPTY, EMPTY, EX(srlw), EMPTY, EMPTY
  };
  idex(pc, &table[decinfo.isa.instr.funct3]);
P
Parallels 已提交
34 35 36
}

static make_EHelper(op) {
37 38 39 40 41 42 43 44 45 46
  static OpcodeEntry table [3][8] = {
    {EX(add), EX(sll), EX(slt), EX(sltu), EX(xor), EX(srl), EX(or), EX(and)},
    {EX(mul), EX(mulh), EX(mulhsu), EX(mulhu), EX(div), EX(divu), EX(rem), EX(remu)},
    {EX(sub), EMPTY, EMPTY, EMPTY, EMPTY, EX(sra), EMPTY, EMPTY},
  };

  uint32_t idx = decinfo.isa.instr.funct7;
  if (idx == 32) idx = 2;
  assert(idx <= 2);
  idex(pc, &table[idx][decinfo.isa.instr.funct3]);
P
Parallels 已提交
47 48
}

49
static make_EHelper(op32) {
50 51 52 53 54 55 56 57 58 59
  static OpcodeEntry table [3][8] = {
    {EX(addw), EX(sllw), EMPTY, EMPTY, EMPTY, EX(srlw), EMPTY, EMPTY},
    {EX(mulw), EMPTY, EMPTY, EMPTY, EX(divw), EX(divuw), EX(remw), EX(remuw)},
    {EX(subw), EMPTY, EMPTY, EMPTY, EMPTY, EX(sraw), EMPTY, EMPTY},
  };

  uint32_t idx = decinfo.isa.instr.funct7;
  if (idx == 32) idx = 2;
  assert(idx <= 2);
  idex(pc, &table[idx][decinfo.isa.instr.funct3]);
P
Parallels 已提交
60 61 62
}

static make_EHelper(system) {
63
  static OpcodeEntry table [8] = {
Z
Zihao Yu 已提交
64
    EX(priv), IDEX(csr, csrrw), IDEX(csr, csrrs), IDEX(csr, csrrc), EMPTY, IDEX(csri, csrrw), IDEX(csri, csrrs), IDEX(csri, csrrc)
65 66
  };
  idex(pc, &table[decinfo.isa.instr.funct3]);
P
Parallels 已提交
67 68
}

Z
Zihao Yu 已提交
69
static make_EHelper(atomic) {
70
  cpu.amo = true;
Z
Zihao Yu 已提交
71
  static OpcodeEntry table_lo [4] = {
Z
Zihao Yu 已提交
72
    EMPTY, EX(amoswap), EX(lr), EX(sc)
Z
Zihao Yu 已提交
73 74
  };
  static OpcodeEntry table_hi [8] = {
Z
Zihao Yu 已提交
75
    EX(amoadd), EX(amoxor), EX(amoor), EX(amoand), EMPTY, EMPTY, EMPTY, EX(amomaxu)
Z
Zihao Yu 已提交
76 77 78 79 80 81 82
  };

  decinfo.width = 1 << decinfo.isa.instr.funct3;

  uint32_t funct5 = decinfo.isa.instr.funct7 >> 2;
  uint32_t idx_lo = funct5 & 0x3;
  uint32_t idx_hi = funct5 >> 2;
83
  if (funct5 == 2) cpu.amo = false; // lr is not a store
Z
Zihao Yu 已提交
84 85
  if (idx_lo != 0) idex(pc, &table_lo[idx_lo]);
  else idex(pc, &table_hi[idx_hi]);
86
  cpu.amo = false;
Z
Zihao Yu 已提交
87 88
}

89 90 91 92
static make_EHelper(fp) {
  longjmp_raise_intr(EX_II);
}

P
Parallels 已提交
93
static OpcodeEntry opcode_table [32] = {
94 95 96
  /* b00 */ IDEX(ld, load), EX(fp), EMPTY, EX(fence), IDEX(I, op_imm), IDEX(U, auipc), IDEX(I, op_imm32), EMPTY,
  /* b01 */ IDEX(st, store), EX(fp), EMPTY, IDEX(R, atomic), IDEX(R, op), IDEX(U, lui), IDEX(R, op32), EMPTY,
  /* b10 */ EX(fp), EMPTY, EMPTY, EMPTY, EX(fp), EMPTY, EMPTY, EMPTY,
P
Parallels 已提交
97 98 99
  /* b11 */ IDEX(B, branch), IDEX(I, jalr), EX(nemu_trap), IDEX(J, jal), EX(system), EMPTY, EMPTY, EMPTY,
};

100 101 102
// RVC

static make_EHelper(C_10_100) {
103
  static OpcodeEntry table [8] = {
Z
Zihao Yu 已提交
104
    EMPTY, EMPTY, IDEX(C_rs1_rs2_0, jalr), IDEX(C_0_rs2_rd, add), EMPTY, EMPTY, IDEX(C_JALR, jalr), IDEX(C_rs1_rs2_rd, add),
105
  };
Z
Zihao Yu 已提交
106 107 108 109 110
  uint32_t cond_c_simm12_not0 = (decinfo.isa.instr.c_simm12 != 0);
  uint32_t cond_c_rd_rs1_not0 = (decinfo.isa.instr.c_rd_rs1 != 0);
  uint32_t cond_c_rs2_not0 = (decinfo.isa.instr.c_rs2 != 0);
  uint32_t idx = (cond_c_simm12_not0 << 2) | (cond_c_rd_rs1_not0 << 1) | cond_c_rs2_not0;
  assert(idx < 8);
111
  idex(pc, &table[idx]);
112 113
}

Z
Zihao Yu 已提交
114
static make_EHelper(C_01_011) {
Z
Zihao Yu 已提交
115
  static OpcodeEntry table [2] = { IDEX(C_0_imm_rd, lui), IDEX(C_ADDI16SP, add)};
Z
Zihao Yu 已提交
116 117 118 119 120 121
  assert(decinfo.isa.instr.c_rd_rs1 != 0);
  int idx = (decinfo.isa.instr.c_rd_rs1 == 2);
  idex(pc, &table[idx]);
}

static make_EHelper(C_01_100) {
Z
Zihao Yu 已提交
122 123 124 125
  uint32_t func = decinfo.isa.instr.c_func6 & 0x3;
  if (func == 3) {
    decode_CR(pc);
    static OpcodeEntry table [8] = {
Z
Zihao Yu 已提交
126
      EX(sub), EX(xor), EX(or), EX(and), EX(subw), EX(addw), EMPTY, EMPTY,
Z
Zihao Yu 已提交
127 128 129 130 131 132 133 134 135
    };

    uint32_t idx2 = (decinfo.isa.instr.c_func6 >> 2) & 0x1;
    uint32_t idx1_0 = decinfo.isa.instr.c_func2;
    uint32_t idx = (idx2 << 2) | idx1_0;
    assert(idx < 8);
    idex(pc, &table[idx]);
  } else {
    decode_C_rs1__imm_rd_(pc);
Z
Zihao Yu 已提交
136
    static OpcodeEntry table [3] = { EX(srl), EX(sra), EX(and) };
Z
Zihao Yu 已提交
137
    idex(pc, &table[func]);
Z
Zihao Yu 已提交
138 139 140
  }
}

141
static OpcodeEntry rvc_table [3][8] = {
142
  {IDEX(C_ADDI4SPN, add), EX(fp), IDEX(C_LW, lds), IDEX(C_LD, ld), EMPTY, EX(fp), IDEX(C_SW, st), IDEX(C_SD, st)},
Z
Zihao Yu 已提交
143
  {IDEX(C_rs1_imm_rd, add), IDEX(C_rs1_imm_rd, addw), IDEX(C_0_imm_rd, add), EX(C_01_011), EX(C_01_100), IDEX(C_J, jal), IDEX(CB, beq), IDEX(CB, bne)},
144
  {IDEX(C_rs1_imm_rd, sll), EX(fp), IDEX(C_LWSP, lds), IDEX(C_LDSP, ld), EX(C_10_100), EX(fp), IDEX(C_SWSP, st), IDEX(C_SDSP, st)}
145 146
};

P
Parallels 已提交
147
void isa_exec(vaddr_t *pc) {
Z
Zihao Yu 已提交
148 149 150 151 152 153 154 155 156
  extern jmp_buf intr_buf;
  int setjmp_ret;
  if ((setjmp_ret = setjmp(intr_buf)) != 0) {
    int exception = setjmp_ret - 1;
    void raise_intr(word_t, vaddr_t);
    raise_intr(exception, cpu.pc);
    return;
  }

Z
Zihao Yu 已提交
157
  cpu.fetching = true;
158 159 160 161 162 163 164 165
  if ((*pc & 0xfff) == 0xffe) {
    // 4 byte instruction accross page boundary
    uint32_t lo = instr_fetch(pc, 2);
    uint32_t hi = instr_fetch(pc, 2);
    decinfo.isa.instr.val = ((hi & 0xffff) << 16) | (lo & 0xffff);
  } else {
    decinfo.isa.instr.val = instr_fetch(pc, 4);
  }
Z
Zihao Yu 已提交
166
  cpu.fetching = false;
167 168 169 170 171 172 173
  if (decinfo.isa.instr.opcode1_0 == 0x3) {
    idex(pc, &opcode_table[decinfo.isa.instr.opcode6_2]);
  } else {
    // RVC instructions are only 2-byte
    *pc -= 2;
    idex(pc, &rvc_table[decinfo.isa.instr.opcode1_0][decinfo.isa.instr.c_funct3]);
  }
P
Parallels 已提交
174
}