exec.c 7.1 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 105 106
  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)
    EX(0x1c, amomaxu)
  }
107
  cpu.amo = false;
Z
Zihao Yu 已提交
108 109
}

Z
Zihao Yu 已提交
110
static inline make_EHelper(fp) {
111
  raise_intr(s, EX_II, cpu.pc);
112 113
}

Z
Zihao Yu 已提交
114 115 116 117 118 119 120 121 122 123 124 125 126
// 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)
127 128 129 130
    default: exec_inv(s);
  }
}

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

Z
Zihao Yu 已提交
141 142 143 144 145 146 147 148 149
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 已提交
150
  } else {
Z
Zihao Yu 已提交
151
    switch (op) {
152 153 154
      IDEX (0, CB_shift, srli)
      IDEX (1, CB_shift, srai)
      IDEX (2, CB_andi, andi)
Z
Zihao Yu 已提交
155
    }
Z
Zihao Yu 已提交
156 157 158
  }
}

Z
Zihao Yu 已提交
159 160
static inline void exec(DecodeExecState *s) {
  if ((s->seq_pc & 0xfff) == 0xffe) {
161
    // instruction may accross page boundary
Z
Zihao Yu 已提交
162
    uint32_t lo = instr_fetch(&s->seq_pc, 2);
Z
Zihao Yu 已提交
163
    check_mem_ex();
Z
Zihao Yu 已提交
164 165
    s->isa.instr.val = lo & 0xffff;
    if (s->isa.instr.r.opcode1_0 != 0x3) {
166 167 168 169 170 171 172
      // 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 已提交
173 174
    uint32_t hi = instr_fetch(&s->seq_pc, 2);
    s->isa.instr.val |= ((hi & 0xffff) << 16);
175
  } else {
176 177
    // in-page instructions, fetch 4 byte and
    // see whether it is an RVC instruction later
Z
Zihao Yu 已提交
178
    s->isa.instr.val = instr_fetch(&s->seq_pc, 4);
179
  }
Z
Zihao Yu 已提交
180

181 182
  check_mem_ex();

Z
Zihao Yu 已提交
183 184
  if (s->isa.instr.r.opcode1_0 == 0x3) {
    switch (s->isa.instr.r.opcode6_2) {
185
      IDEX (000, I, load)   EX   (001, fp)                                  EX   (003, fence)
Z
Zihao Yu 已提交
186
      IDEX (004, I, op_imm) IDEX (005, U, auipc)  IDEX (006, I, op_imm32)
187
      IDEX (010, S, store)  EX   (011, fp)                                  IDEX (013, R, atomic)
Z
Zihao Yu 已提交
188 189 190 191 192 193 194
      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);
    }
195 196
  } else {
    // RVC instructions are only 2-byte
Z
Zihao Yu 已提交
197 198 199 200 201
    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) {
202
      IDEX (000, C_ADDI4SPN, addi)EX   (001, fp)  IDEXW(002, C_LW, lds, 4)  IDEXW(003, C_LD, ld, 8)
Z
Zihao Yu 已提交
203
                            EX   (005, fp)        IDEXW(006, C_SW, st, 4)   IDEXW(007, C_SD, st, 8)
204
      IDEX (010, CI_simm, addi)IDEX (011, CI_simm, addiw)IDEX (012, C_LI, addi)EX   (013, lui_addi16sp)
Z
Zihao Yu 已提交
205
      EX   (014, misc_alu)  IDEX (015, C_J, jal)  IDEX (016, CB, beq)       IDEX (017, CB, bne)
206
      IDEX (020, CI_uimm, slli)EX   (021, fp)     IDEXW(022, C_LWSP, lds, 4)IDEXW(023, C_LDSP, ld, 8)
Z
Zihao Yu 已提交
207 208 209
      EX   (024, misc)      EX   (025, fp)        IDEXW(026, C_SWSP, st, 4) IDEXW(027, C_SDSP, st, 8)
      default: exec_inv(s);
    }
210
  }
P
Parallels 已提交
211
}
Z
Zihao Yu 已提交
212 213 214 215 216 217 218

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

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

#if !defined(DIFF_TEST) && !_SHARE
  void query_intr(DecodeExecState *s);
  query_intr(&s);
228
#endif
Z
Zihao Yu 已提交
229 230
  return s.seq_pc;
}