exec.c 7.2 KB
Newer Older
1 2 3
#include <cpu/exec.h>
#include "../local-include/decode.h"
#include "../local-include/intr.h"
P
Parallels 已提交
4 5
#include "all-instr.h"

6 7 8 9
#define decode_empty(s)

static inline void set_width(DecodeExecState *s, int width) {
  if (width != 0) s->width = width;
P
Parallels 已提交
10 11
}

12 13 14 15 16 17 18 19 20 21 22 23 24 25
#define IDEXW(idx, id, ex, w) CASE_ENTRY(idx, concat(decode_, id), concat(exec_, ex), w)
#define IDEX(idx, id, ex)     IDEXW(idx, id, ex, 0)
#define EXW(idx, ex, w)       IDEXW(idx, empty, ex, w)
#define EX(idx, ex)           EXW(idx, ex, 0)
#define EMPTY(idx)            //EX(idx, inv)

#define CASE_ENTRY(idx, id, ex, w) case idx: set_width(s, w); id(s); ex(s); break;

static inline make_EHelper(load) {
  switch (s->isa.instr.i.funct3) {
    EXW(0, lds, 1) EXW(1, lds, 2) EXW(2, lds, 4) EXW(3, ld, 8)
    EXW(4, ld, 1)  EXW(5, ld, 2)  EXW(6, ld, 4)
    default: exec_inv(s);
  }
P
Parallels 已提交
26 27
}

28 29 30 31
static inline make_EHelper(store) {
  switch (s->isa.instr.s.funct3) {
    EXW(0, st, 1) EXW(1, st, 2) EXW(2, st, 4) EXW(3, st, 8)
  }
P
Parallels 已提交
32 33
}

34 35
static inline make_EHelper(op_imm) {
  switch (s->isa.instr.i.funct3) {
36 37
    EX(0, addi)  EX(1, slli)  EX(2, slti) EX(3, sltui)
    EX(4, xori)  EX(5, srli)  EX(6, ori)  EX(7, andi)
38
  }
P
Parallels 已提交
39 40
}

Z
Zihao Yu 已提交
41
static inline make_EHelper(op_imm32) {
42
  switch (s->isa.instr.i.funct3) {
43
    EX(0, addiw) EX(1, slliw) EX(5, srliw)
44 45 46
    default: exec_inv(s);
  }
}
47

48 49
static inline make_EHelper(op) {
  uint32_t idx = s->isa.instr.r.funct7;
50 51
  if (idx == 32) idx = 2;
  assert(idx <= 2);
52 53 54 55 56 57 58 59 60 61
#define pair(x, y) (((x) << 3) | (y))
  switch (pair(idx, s->isa.instr.r.funct3)) {
    EX(pair(0, 0), add)  EX(pair(0, 1), sll)  EX(pair(0, 2), slt)  EX(pair(0, 3), sltu)
    EX(pair(0, 4), xor)  EX(pair(0, 5), srl)  EX(pair(0, 6), or)   EX(pair(0, 7), and)
    EX(pair(1, 0), mul)  EX(pair(1, 1), mulh) EX(pair(1,2), mulhsu)EX(pair(1, 3), mulhu)
    EX(pair(1, 4), div)  EX(pair(1, 5), divu) EX(pair(1, 6), rem)  EX(pair(1, 7), remu)
    EX(pair(2, 0), sub)  EX(pair(2, 5), sra)
    default: exec_inv(s);
  }
#undef pair
P
Parallels 已提交
62 63
}

64

Z
Zihao Yu 已提交
65
static inline make_EHelper(op32) {
66
  uint32_t idx = s->isa.instr.r.funct7;
67 68
  if (idx == 32) idx = 2;
  assert(idx <= 2);
69 70 71 72 73 74 75 76 77 78
#define pair(x, y) (((x) << 3) | (y))
  switch (pair(idx, s->isa.instr.r.funct3)) {
    EX(pair(0, 0), addw) EX(pair(0, 1), sllw)
                         EX(pair(0, 5), srlw)
    EX(pair(1, 0), mulw)
    EX(pair(1, 4), divw) EX(pair(1, 5), divuw) EX(pair(1, 6), remw)  EX(pair(1, 7), remuw)
    EX(pair(2, 0), subw) EX(pair(2, 5), sraw)
    default: exec_inv(s);
  }
#undef pair
P
Parallels 已提交
79 80
}

81 82 83 84 85
static inline make_EHelper(branch) {
  switch (s->isa.instr.i.funct3) {
    EX(0, beq)  EX(1, bne)  EMPTY(2)   EMPTY(3)
    EX(4, blt)  EX(5, bge)  EX(6, bltu)EX(7, bgeu)
  }
P
Parallels 已提交
86 87
}

88 89 90
static inline make_EHelper(system) {
  switch (s->isa.instr.i.funct3) {
    EX(0, priv)  IDEX(1, csr, csrrw)  IDEX(2, csr, csrrs)  IDEX(3, csr, csrrc)
91
    EMPTY(4)     IDEX(5, csri, csrrwi)IDEX(6, csri, csrrsi)IDEX(7, csri, csrrci)
92 93
  }
}
Z
Zihao Yu 已提交
94

95 96 97
static inline make_EHelper(atomic) {
  cpu.amo = true;
  uint32_t funct5 = s->isa.instr.r.funct7 >> 2;
98
  if (funct5 == 2) cpu.amo = false; // lr is not a store
99 100 101 102 103 104
  set_width(s, 1 << s->isa.instr.r.funct3);
  switch (funct5) {
    EX(0x00, amoadd) EX(0x01, amoswap) EX(0x02, lr) EX(0x03, sc)
    EX(0x04, amoxor)
    EX(0x0c, amoand)
    EX(0x08, amoor)
105 106 107
    EX(0x10, amomin)
    EX(0x14, amomax)
    EX(0x18, amominu)
108 109
    EX(0x1c, amomaxu)
  }
110
  cpu.amo = false;
Z
Zihao Yu 已提交
111 112
}

Z
Zihao Yu 已提交
113
static inline make_EHelper(fp) {
114
  raise_intr(s, EX_II, cpu.pc);
115 116
}

Z
Zihao Yu 已提交
117 118 119 120 121 122 123 124 125 126 127 128 129
// RVC

static inline make_EHelper(misc) {
  uint32_t instr = s->isa.instr.val;
  uint32_t bits12not0 = (BITS(instr, 12, 12) != 0);
  uint32_t bits11_7not0 = (BITS(instr, 11, 7) != 0);
  uint32_t bits6_2not0 = (BITS(instr, 6, 2) != 0);
  uint32_t op = (bits12not0 << 2) | (bits11_7not0 << 1) | bits6_2not0;
  switch (op) {
    IDEX (0b010, C_JR, jalr)
    IDEX (0b011, C_MOV, add)
    IDEX (0b110, C_JALR, jalr)
    IDEX (0b111, C_ADD, add)
130 131 132 133
    default: exec_inv(s);
  }
}

Z
Zihao Yu 已提交
134 135 136 137
static inline make_EHelper(lui_addi16sp) {
  uint32_t rd = BITS(s->isa.instr.val, 11, 7);
  assert(rd != 0);
  switch (rd) {
138
    IDEX (2, C_ADDI16SP, addi)
Z
Zihao Yu 已提交
139
    default: // and other cases
140
    IDEX (1, CI_simm_lui, lui)
Z
Zihao Yu 已提交
141
  }
142
}
P
Parallels 已提交
143

Z
Zihao Yu 已提交
144 145 146 147 148 149 150 151 152
static inline make_EHelper(misc_alu) {
  uint32_t instr = s->isa.instr.val;
  uint32_t op = BITS(instr, 11, 10);
  if (op == 3) {
    uint32_t op2 = (BITS(instr, 12, 12) << 2) | BITS(instr, 6, 5);
    switch (op2) {
      IDEX (0, CS, sub) IDEX (1, CS, xor) IDEX (2, CS, or)  IDEX (3, CS, and)
      IDEX (4, CS, subw)IDEX (5, CS, addw)EMPTY(6)          EMPTY(7)
    }
Z
Zihao Yu 已提交
153
  } else {
Z
Zihao Yu 已提交
154
    switch (op) {
155 156 157
      IDEX (0, CB_shift, srli)
      IDEX (1, CB_shift, srai)
      IDEX (2, CB_andi, andi)
Z
Zihao Yu 已提交
158
    }
Z
Zihao Yu 已提交
159 160 161
  }
}

Z
Zihao Yu 已提交
162 163
static inline void exec(DecodeExecState *s) {
  if ((s->seq_pc & 0xfff) == 0xffe) {
164
    // instruction may accross page boundary
Z
Zihao Yu 已提交
165
    uint32_t lo = instr_fetch(&s->seq_pc, 2);
166
    return_on_mem_ex();
Z
Zihao Yu 已提交
167 168
    s->isa.instr.val = lo & 0xffff;
    if (s->isa.instr.r.opcode1_0 != 0x3) {
169 170 171 172 173 174 175
      // this is an RVC instruction
      goto rvc;
    }
    // this is a 4-byte instruction, should fetch the MSB part
    // NOTE: The fetch here may cause IPF.
    // If it is the case, we should have mepc = xxxffe and mtval = yyy000.
    // Refer to `mtval` in the privileged manual for more details.
Z
Zihao Yu 已提交
176 177
    uint32_t hi = instr_fetch(&s->seq_pc, 2);
    s->isa.instr.val |= ((hi & 0xffff) << 16);
178
  } else {
179 180
    // in-page instructions, fetch 4 byte and
    // see whether it is an RVC instruction later
Z
Zihao Yu 已提交
181
    s->isa.instr.val = instr_fetch(&s->seq_pc, 4);
182
  }
Z
Zihao Yu 已提交
183

184
  return_on_mem_ex();
185

Z
Zihao Yu 已提交
186 187
  if (s->isa.instr.r.opcode1_0 == 0x3) {
    switch (s->isa.instr.r.opcode6_2) {
188
      IDEX (000, I, load)   EX   (001, fp)                                  EX   (003, fence)
Z
Zihao Yu 已提交
189
      IDEX (004, I, op_imm) IDEX (005, U, auipc)  IDEX (006, I, op_imm32)
190
      IDEX (010, S, store)  EX   (011, fp)                                  IDEX (013, R, atomic)
Z
Zihao Yu 已提交
191 192 193 194 195 196 197
      IDEX (014, R, op)     IDEX (015, U, lui)    IDEX (016, R, op32)
      EX   (020, fp)
      EX   (024, fp)
      IDEX (030, B, branch) IDEX (031, I, jalr)   EX   (032, nemu_trap)     IDEX (033, J, jal)
      EX   (034, system)
      default: exec_inv(s);
    }
198 199
  } else {
    // RVC instructions are only 2-byte
Z
Zihao Yu 已提交
200 201 202 203 204
    s->seq_pc -= 2;
rvc: ;
    //idex(pc, &rvc_table[decinfo.isa.instr.opcode1_0][decinfo.isa.instr.c_funct3]);
    uint32_t rvc_opcode = (s->isa.instr.r.opcode1_0 << 3) | BITS(s->isa.instr.val, 15, 13);
    switch (rvc_opcode) {
205
      IDEX (000, C_ADDI4SPN, addi)EX   (001, fp)  IDEXW(002, C_LW, lds, 4)  IDEXW(003, C_LD, ld, 8)
Z
Zihao Yu 已提交
206
                            EX   (005, fp)        IDEXW(006, C_SW, st, 4)   IDEXW(007, C_SD, st, 8)
207
      IDEX (010, CI_simm, addi)IDEX (011, CI_simm, addiw)IDEX (012, C_LI, addi)EX   (013, lui_addi16sp)
Z
Zihao Yu 已提交
208
      EX   (014, misc_alu)  IDEX (015, C_J, jal)  IDEX (016, CB, beq)       IDEX (017, CB, bne)
209
      IDEX (020, CI_uimm, slli)EX   (021, fp)     IDEXW(022, C_LWSP, lds, 4)IDEXW(023, C_LDSP, ld, 8)
Z
Zihao Yu 已提交
210 211 212
      EX   (024, misc)      EX   (025, fp)        IDEXW(026, C_SWSP, st, 4) IDEXW(027, C_SDSP, st, 8)
      default: exec_inv(s);
    }
213
  }
P
Parallels 已提交
214
}
Z
Zihao Yu 已提交
215 216 217 218 219 220 221

vaddr_t isa_exec_once() {
  DecodeExecState s;
  s.is_jmp = 0;
  s.seq_pc = cpu.pc;

  exec(&s);
222 223 224 225
  if (cpu.mem_exception != MEM_OK) {
    raise_intr(&s, cpu.mem_exception, cpu.pc);
    cpu.mem_exception = MEM_OK;
  }
Z
Zihao Yu 已提交
226 227 228 229 230
  update_pc(&s);

#if !defined(DIFF_TEST) && !_SHARE
  void query_intr(DecodeExecState *s);
  query_intr(&s);
231
#endif
232 233 234 235

  // reset gpr[0]
  reg_l(0) = 0;

Z
Zihao Yu 已提交
236 237
  return s.seq_pc;
}