]> Git Repo - binutils.git/blob - sim/riscv/sim-main.c
Automatic date update in version.in
[binutils.git] / sim / riscv / sim-main.c
1 /* RISC-V simulator.
2
3    Copyright (C) 2005-2022 Free Software Foundation, Inc.
4    Contributed by Mike Frysinger.
5
6    This file is part of simulators.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 /* This file contains the main simulator decoding logic.  i.e. everything that
22    is architecture specific.  */
23
24 /* This must come before any other includes.  */
25 #include "defs.h"
26
27 #include <inttypes.h>
28 #include <time.h>
29
30 #include "sim-main.h"
31 #include "sim-signal.h"
32 #include "sim-syscall.h"
33
34 #include "opcode/riscv.h"
35
36 #include "gdb/sim-riscv.h"
37 \f
38 #define TRACE_REG(cpu, reg) \
39   TRACE_REGISTER (cpu, "wrote %s = %#" PRIxTW, riscv_gpr_names_abi[reg], \
40                   cpu->regs[reg])
41 \f
42 static const struct riscv_opcode *riscv_hash[OP_MASK_OP + 1];
43 #define OP_HASH_IDX(i) ((i) & (riscv_insn_length (i) == 2 ? 0x3 : 0x7f))
44
45 #define RISCV_ASSERT_RV32(cpu, fmt, args...) \
46   do { \
47     if (RISCV_XLEN (cpu) != 32) \
48       { \
49         SIM_DESC sd = CPU_STATE (cpu); \
50         TRACE_INSN (cpu, "RV32I-only " fmt, ## args); \
51         sim_engine_halt (sd, cpu, NULL, cpu->pc, sim_signalled, SIM_SIGILL); \
52       } \
53   } while (0)
54
55 #define RISCV_ASSERT_RV64(cpu, fmt, args...) \
56   do { \
57     if (RISCV_XLEN (cpu) != 64) \
58       { \
59         SIM_DESC sd = CPU_STATE (cpu); \
60         TRACE_INSN (cpu, "RV64I-only " fmt, ## args); \
61         sim_engine_halt (sd, cpu, NULL, cpu->pc, sim_signalled, SIM_SIGILL); \
62       } \
63   } while (0)
64
65 static INLINE void
66 store_rd (SIM_CPU *cpu, int rd, unsigned_word val)
67 {
68   if (rd)
69     {
70       cpu->regs[rd] = val;
71       TRACE_REG (cpu, rd);
72     }
73 }
74
75 static INLINE unsigned_word
76 fetch_csr (SIM_CPU *cpu, const char *name, int csr, unsigned_word *reg)
77 {
78   /* Handle pseudo registers.  */
79   switch (csr)
80     {
81     /* Allow certain registers only in respective modes.  */
82     case CSR_CYCLEH:
83     case CSR_INSTRETH:
84     case CSR_TIMEH:
85       RISCV_ASSERT_RV32 (cpu, "CSR: %s", name);
86       break;
87     }
88
89   return *reg;
90 }
91
92 static INLINE void
93 store_csr (SIM_CPU *cpu, const char *name, int csr, unsigned_word *reg,
94            unsigned_word val)
95 {
96   switch (csr)
97     {
98     /* These are pseudo registers that modify sub-fields of fcsr.  */
99     case CSR_FRM:
100       val &= 0x7;
101       *reg = val;
102       cpu->csr.fcsr = (cpu->csr.fcsr & ~0xe0) | (val << 5);
103       break;
104     case CSR_FFLAGS:
105       val &= 0x1f;
106       *reg = val;
107       cpu->csr.fcsr = (cpu->csr.fcsr & ~0x1f) | val;
108       break;
109     /* Keep the sub-fields in sync.  */
110     case CSR_FCSR:
111       *reg = val;
112       cpu->csr.frm = (val >> 5) & 0x7;
113       cpu->csr.fflags = val & 0x1f;
114       break;
115
116     /* Allow certain registers only in respective modes.  */
117     case CSR_CYCLEH:
118     case CSR_INSTRETH:
119     case CSR_TIMEH:
120       RISCV_ASSERT_RV32 (cpu, "CSR: %s", name);
121
122     /* All the rest are immutable.  */
123     default:
124       val = *reg;
125       break;
126     }
127
128   TRACE_REGISTER (cpu, "wrote CSR %s = %#" PRIxTW, name, val);
129 }
130
131 static inline unsigned_word
132 ashiftrt (unsigned_word val, unsigned_word shift)
133 {
134   uint32_t sign = (val & 0x80000000) ? ~(0xfffffffful >> shift) : 0;
135   return (val >> shift) | sign;
136 }
137
138 static inline unsigned_word
139 ashiftrt64 (unsigned_word val, unsigned_word shift)
140 {
141   uint64_t sign =
142     (val & 0x8000000000000000ull) ? ~(0xffffffffffffffffull >> shift) : 0;
143   return (val >> shift) | sign;
144 }
145
146 static sim_cia
147 execute_i (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
148 {
149   SIM_DESC sd = CPU_STATE (cpu);
150   int rd = (iw >> OP_SH_RD) & OP_MASK_RD;
151   int rs1 = (iw >> OP_SH_RS1) & OP_MASK_RS1;
152   int rs2 = (iw >> OP_SH_RS2) & OP_MASK_RS2;
153   const char *rd_name = riscv_gpr_names_abi[rd];
154   const char *rs1_name = riscv_gpr_names_abi[rs1];
155   const char *rs2_name = riscv_gpr_names_abi[rs2];
156   unsigned int csr = (iw >> OP_SH_CSR) & OP_MASK_CSR;
157   unsigned_word i_imm = EXTRACT_ITYPE_IMM (iw);
158   unsigned_word u_imm = EXTRACT_UTYPE_IMM ((uint64_t) iw);
159   unsigned_word s_imm = EXTRACT_STYPE_IMM (iw);
160   unsigned_word sb_imm = EXTRACT_BTYPE_IMM (iw);
161   unsigned_word shamt_imm = ((iw >> OP_SH_SHAMT) & OP_MASK_SHAMT);
162   unsigned_word tmp;
163   sim_cia pc = cpu->pc + 4;
164
165   TRACE_EXTRACT (cpu,
166                  "rd:%-2i:%-4s  "
167                  "rs1:%-2i:%-4s %0*" PRIxTW "  "
168                  "rs2:%-2i:%-4s %0*" PRIxTW "  "
169                  "match:%#x mask:%#x",
170                  rd, rd_name,
171                  rs1, rs1_name, (int) sizeof (unsigned_word) * 2, cpu->regs[rs1],
172                  rs2, rs2_name, (int) sizeof (unsigned_word) * 2, cpu->regs[rs2],
173                  (unsigned) op->match, (unsigned) op->mask);
174
175   switch (op->match)
176     {
177     case MATCH_ADD:
178       TRACE_INSN (cpu, "add %s, %s, %s;  // %s = %s + %s",
179                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
180       store_rd (cpu, rd, cpu->regs[rs1] + cpu->regs[rs2]);
181       break;
182     case MATCH_ADDW:
183       TRACE_INSN (cpu, "addw %s, %s, %s;  // %s = %s + %s",
184                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
185       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
186       store_rd (cpu, rd, EXTEND32 (cpu->regs[rs1] + cpu->regs[rs2]));
187       break;
188     case MATCH_ADDI:
189       TRACE_INSN (cpu, "addi %s, %s, %#" PRIxTW ";  // %s = %s + %#" PRIxTW,
190                   rd_name, rs1_name, i_imm, rd_name, rs1_name, i_imm);
191       store_rd (cpu, rd, cpu->regs[rs1] + i_imm);
192       break;
193     case MATCH_ADDIW:
194       TRACE_INSN (cpu, "addiw %s, %s, %#" PRIxTW ";  // %s = %s + %#" PRIxTW,
195                   rd_name, rs1_name, i_imm, rd_name, rs1_name, i_imm);
196       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
197       store_rd (cpu, rd, EXTEND32 (cpu->regs[rs1] + i_imm));
198       break;
199     case MATCH_AND:
200       TRACE_INSN (cpu, "and %s, %s, %s;  // %s = %s & %s",
201                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
202       store_rd (cpu, rd, cpu->regs[rs1] & cpu->regs[rs2]);
203       break;
204     case MATCH_ANDI:
205       TRACE_INSN (cpu, "andi %s, %s, %" PRIiTW ";  // %s = %s & %#" PRIxTW,
206                   rd_name, rs1_name, i_imm, rd_name, rs1_name, i_imm);
207       store_rd (cpu, rd, cpu->regs[rs1] & i_imm);
208       break;
209     case MATCH_OR:
210       TRACE_INSN (cpu, "or %s, %s, %s;  // %s = %s | %s",
211                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
212       store_rd (cpu, rd, cpu->regs[rs1] | cpu->regs[rs2]);
213       break;
214     case MATCH_ORI:
215       TRACE_INSN (cpu, "ori %s, %s, %" PRIiTW ";  // %s = %s | %#" PRIxTW,
216                   rd_name, rs1_name, i_imm, rd_name, rs1_name, i_imm);
217       store_rd (cpu, rd, cpu->regs[rs1] | i_imm);
218       break;
219     case MATCH_XOR:
220       TRACE_INSN (cpu, "xor %s, %s, %s;  // %s = %s ^ %s",
221                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
222       store_rd (cpu, rd, cpu->regs[rs1] ^ cpu->regs[rs2]);
223       break;
224     case MATCH_XORI:
225       TRACE_INSN (cpu, "xori %s, %s, %" PRIiTW ";  // %s = %s ^ %#" PRIxTW,
226                   rd_name, rs1_name, i_imm, rd_name, rs1_name, i_imm);
227       store_rd (cpu, rd, cpu->regs[rs1] ^ i_imm);
228       break;
229     case MATCH_SUB:
230       TRACE_INSN (cpu, "sub %s, %s, %s;  // %s = %s - %s",
231                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
232       store_rd (cpu, rd, cpu->regs[rs1] - cpu->regs[rs2]);
233       break;
234     case MATCH_SUBW:
235       TRACE_INSN (cpu, "subw %s, %s, %s;  // %s = %s - %s",
236                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
237       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
238       store_rd (cpu, rd, EXTEND32 (cpu->regs[rs1] - cpu->regs[rs2]));
239       break;
240     case MATCH_LUI:
241       TRACE_INSN (cpu, "lui %s, %#" PRIxTW ";", rd_name, u_imm);
242       store_rd (cpu, rd, u_imm);
243       break;
244     case MATCH_SLL:
245       TRACE_INSN (cpu, "sll %s, %s, %s;  // %s = %s << %s",
246                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
247       u_imm = RISCV_XLEN (cpu) == 32 ? 0x1f : 0x3f;
248       store_rd (cpu, rd, cpu->regs[rs1] << (cpu->regs[rs2] & u_imm));
249       break;
250     case MATCH_SLLW:
251       TRACE_INSN (cpu, "sllw %s, %s, %s;  // %s = %s << %s",
252                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
253       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
254       store_rd (cpu, rd, EXTEND32 (
255         (uint32_t) cpu->regs[rs1] << (cpu->regs[rs2] & 0x1f)));
256       break;
257     case MATCH_SLLI:
258       TRACE_INSN (cpu, "slli %s, %s, %" PRIiTW ";  // %s = %s << %#" PRIxTW,
259                   rd_name, rs1_name, shamt_imm, rd_name, rs1_name, shamt_imm);
260       if (RISCV_XLEN (cpu) == 32 && shamt_imm > 0x1f)
261         sim_engine_halt (sd, cpu, NULL, cpu->pc, sim_signalled, SIM_SIGILL);
262       store_rd (cpu, rd, cpu->regs[rs1] << shamt_imm);
263       break;
264     case MATCH_SLLIW:
265       TRACE_INSN (cpu, "slliw %s, %s, %" PRIiTW ";  // %s = %s << %#" PRIxTW,
266                   rd_name, rs1_name, shamt_imm, rd_name, rs1_name, shamt_imm);
267       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
268       store_rd (cpu, rd, EXTEND32 ((uint32_t) cpu->regs[rs1] << shamt_imm));
269       break;
270     case MATCH_SRL:
271       TRACE_INSN (cpu, "srl %s, %s, %s;  // %s = %s >> %s",
272                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
273       u_imm = RISCV_XLEN (cpu) == 32 ? 0x1f : 0x3f;
274       store_rd (cpu, rd, cpu->regs[rs1] >> (cpu->regs[rs2] & u_imm));
275       break;
276     case MATCH_SRLW:
277       TRACE_INSN (cpu, "srlw %s, %s, %s;  // %s = %s >> %s",
278                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
279       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
280       store_rd (cpu, rd, EXTEND32 (
281         (uint32_t) cpu->regs[rs1] >> (cpu->regs[rs2] & 0x1f)));
282       break;
283     case MATCH_SRLI:
284       TRACE_INSN (cpu, "srli %s, %s, %" PRIiTW ";  // %s = %s >> %#" PRIxTW,
285                   rd_name, rs1_name, shamt_imm, rd_name, rs1_name, shamt_imm);
286       if (RISCV_XLEN (cpu) == 32 && shamt_imm > 0x1f)
287         sim_engine_halt (sd, cpu, NULL, cpu->pc, sim_signalled, SIM_SIGILL);
288       store_rd (cpu, rd, cpu->regs[rs1] >> shamt_imm);
289       break;
290     case MATCH_SRLIW:
291       TRACE_INSN (cpu, "srliw %s, %s, %" PRIiTW ";  // %s = %s >> %#" PRIxTW,
292                   rd_name, rs1_name, shamt_imm, rd_name, rs1_name, shamt_imm);
293       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
294       store_rd (cpu, rd, EXTEND32 ((uint32_t) cpu->regs[rs1] >> shamt_imm));
295       break;
296     case MATCH_SRA:
297       TRACE_INSN (cpu, "sra %s, %s, %s;  // %s = %s >>> %s",
298                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
299       if (RISCV_XLEN (cpu) == 32)
300         tmp = ashiftrt (cpu->regs[rs1], cpu->regs[rs2] & 0x1f);
301       else
302         tmp = ashiftrt64 (cpu->regs[rs1], cpu->regs[rs2] & 0x3f);
303       store_rd (cpu, rd, tmp);
304       break;
305     case MATCH_SRAW:
306       TRACE_INSN (cpu, "sraw %s, %s, %s;  // %s = %s >>> %s",
307                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
308       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
309       store_rd (cpu, rd, EXTEND32 (
310         ashiftrt ((int32_t) cpu->regs[rs1], cpu->regs[rs2] & 0x1f)));
311       break;
312     case MATCH_SRAI:
313       TRACE_INSN (cpu, "srai %s, %s, %" PRIiTW ";  // %s = %s >>> %#" PRIxTW,
314                   rd_name, rs1_name, shamt_imm, rd_name, rs1_name, shamt_imm);
315       if (RISCV_XLEN (cpu) == 32)
316         {
317           if (shamt_imm > 0x1f)
318             sim_engine_halt (sd, cpu, NULL, cpu->pc, sim_signalled, SIM_SIGILL);
319           tmp = ashiftrt (cpu->regs[rs1], shamt_imm);
320         }
321       else
322         tmp = ashiftrt64 (cpu->regs[rs1], shamt_imm);
323       store_rd (cpu, rd, tmp);
324       break;
325     case MATCH_SRAIW:
326       TRACE_INSN (cpu, "sraiw %s, %s, %" PRIiTW ";  // %s = %s >>> %#" PRIxTW,
327                   rd_name, rs1_name, shamt_imm, rd_name, rs1_name, shamt_imm);
328       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
329       store_rd (cpu, rd, EXTEND32 (
330         ashiftrt ((int32_t) cpu->regs[rs1], shamt_imm)));
331       break;
332     case MATCH_SLT:
333       TRACE_INSN (cpu, "slt");
334       store_rd (cpu, rd,
335                 !!((signed_word) cpu->regs[rs1] < (signed_word) cpu->regs[rs2]));
336       break;
337     case MATCH_SLTU:
338       TRACE_INSN (cpu, "sltu");
339       store_rd (cpu, rd, !!((unsigned_word) cpu->regs[rs1] <
340                             (unsigned_word) cpu->regs[rs2]));
341       break;
342     case MATCH_SLTI:
343       TRACE_INSN (cpu, "slti");
344       store_rd (cpu, rd, !!((signed_word) cpu->regs[rs1] <
345                             (signed_word) i_imm));
346       break;
347     case MATCH_SLTIU:
348       TRACE_INSN (cpu, "sltiu");
349       store_rd (cpu, rd, !!((unsigned_word) cpu->regs[rs1] <
350                             (unsigned_word) i_imm));
351       break;
352     case MATCH_AUIPC:
353       TRACE_INSN (cpu, "auipc %s, %" PRIiTW ";  // %s = pc + %" PRIiTW,
354                   rd_name, u_imm, rd_name, u_imm);
355       store_rd (cpu, rd, cpu->pc + u_imm);
356       break;
357     case MATCH_BEQ:
358       TRACE_INSN (cpu, "beq %s, %s, %#" PRIxTW ";  "
359                        "// if (%s == %s) goto %#" PRIxTW,
360                   rs1_name, rs2_name, sb_imm, rs1_name, rs2_name, sb_imm);
361       if (cpu->regs[rs1] == cpu->regs[rs2])
362         {
363           pc = cpu->pc + sb_imm;
364           TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
365         }
366       break;
367     case MATCH_BLT:
368       TRACE_INSN (cpu, "blt %s, %s, %#" PRIxTW ";  "
369                        "// if (%s < %s) goto %#" PRIxTW,
370                   rs1_name, rs2_name, sb_imm, rs1_name, rs2_name, sb_imm);
371       if ((signed_word) cpu->regs[rs1] < (signed_word) cpu->regs[rs2])
372         {
373           pc = cpu->pc + sb_imm;
374           TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
375         }
376       break;
377     case MATCH_BLTU:
378       TRACE_INSN (cpu, "bltu %s, %s, %#" PRIxTW ";  "
379                        "// if (%s < %s) goto %#" PRIxTW,
380                   rs1_name, rs2_name, sb_imm, rs1_name, rs2_name, sb_imm);
381       if ((unsigned_word) cpu->regs[rs1] < (unsigned_word) cpu->regs[rs2])
382         {
383           pc = cpu->pc + sb_imm;
384           TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
385         }
386       break;
387     case MATCH_BGE:
388       TRACE_INSN (cpu, "bge %s, %s, %#" PRIxTW ";  "
389                        "// if (%s >= %s) goto %#" PRIxTW,
390                   rs1_name, rs2_name, sb_imm, rs1_name, rs2_name, sb_imm);
391       if ((signed_word) cpu->regs[rs1] >= (signed_word) cpu->regs[rs2])
392         {
393           pc = cpu->pc + sb_imm;
394           TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
395         }
396       break;
397     case MATCH_BGEU:
398       TRACE_INSN (cpu, "bgeu %s, %s, %#" PRIxTW ";  "
399                        "// if (%s >= %s) goto %#" PRIxTW,
400                   rs1_name, rs2_name, sb_imm, rs1_name, rs2_name, sb_imm);
401       if ((unsigned_word) cpu->regs[rs1] >= (unsigned_word) cpu->regs[rs2])
402         {
403           pc = cpu->pc + sb_imm;
404           TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
405         }
406       break;
407     case MATCH_BNE:
408       TRACE_INSN (cpu, "bne %s, %s, %#" PRIxTW ";  "
409                        "// if (%s != %s) goto %#" PRIxTW,
410                   rs1_name, rs2_name, sb_imm, rs1_name, rs2_name, sb_imm);
411       if (cpu->regs[rs1] != cpu->regs[rs2])
412         {
413           pc = cpu->pc + sb_imm;
414           TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
415         }
416       break;
417     case MATCH_JAL:
418       TRACE_INSN (cpu, "jal %s, %" PRIiTW ";", rd_name,
419                   EXTRACT_JTYPE_IMM (iw));
420       store_rd (cpu, rd, cpu->pc + 4);
421       pc = cpu->pc + EXTRACT_JTYPE_IMM (iw);
422       TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
423       break;
424     case MATCH_JALR:
425       TRACE_INSN (cpu, "jalr %s, %s, %" PRIiTW ";", rd_name, rs1_name, i_imm);
426       store_rd (cpu, rd, cpu->pc + 4);
427       pc = cpu->regs[rs1] + i_imm;
428       TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
429       break;
430
431     case MATCH_LD:
432       TRACE_INSN (cpu, "ld %s, %" PRIiTW "(%s);",
433                   rd_name, i_imm, rs1_name);
434       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
435       store_rd (cpu, rd,
436         sim_core_read_unaligned_8 (cpu, cpu->pc, read_map,
437                                    cpu->regs[rs1] + i_imm));
438       break;
439     case MATCH_LW:
440       TRACE_INSN (cpu, "lw %s, %" PRIiTW "(%s);",
441                   rd_name, i_imm, rs1_name);
442       store_rd (cpu, rd, EXTEND32 (
443         sim_core_read_unaligned_4 (cpu, cpu->pc, read_map,
444                                    cpu->regs[rs1] + i_imm)));
445       break;
446     case MATCH_LWU:
447       TRACE_INSN (cpu, "lwu %s, %" PRIiTW "(%s);",
448                   rd_name, i_imm, rs1_name);
449       store_rd (cpu, rd,
450         sim_core_read_unaligned_4 (cpu, cpu->pc, read_map,
451                                    cpu->regs[rs1] + i_imm));
452       break;
453     case MATCH_LH:
454       TRACE_INSN (cpu, "lh %s, %" PRIiTW "(%s);",
455                   rd_name, i_imm, rs1_name);
456       store_rd (cpu, rd, EXTEND16 (
457         sim_core_read_unaligned_2 (cpu, cpu->pc, read_map,
458                                    cpu->regs[rs1] + i_imm)));
459       break;
460     case MATCH_LHU:
461       TRACE_INSN (cpu, "lbu %s, %" PRIiTW "(%s);",
462                   rd_name, i_imm, rs1_name);
463       store_rd (cpu, rd,
464         sim_core_read_unaligned_2 (cpu, cpu->pc, read_map,
465                                    cpu->regs[rs1] + i_imm));
466       break;
467     case MATCH_LB:
468       TRACE_INSN (cpu, "lb %s, %" PRIiTW "(%s);",
469                   rd_name, i_imm, rs1_name);
470       store_rd (cpu, rd, EXTEND8 (
471         sim_core_read_unaligned_1 (cpu, cpu->pc, read_map,
472                                    cpu->regs[rs1] + i_imm)));
473       break;
474     case MATCH_LBU:
475       TRACE_INSN (cpu, "lbu %s, %" PRIiTW "(%s);",
476                   rd_name, i_imm, rs1_name);
477       store_rd (cpu, rd,
478         sim_core_read_unaligned_1 (cpu, cpu->pc, read_map,
479                                    cpu->regs[rs1] + i_imm));
480       break;
481     case MATCH_SD:
482       TRACE_INSN (cpu, "sd %s, %" PRIiTW "(%s);",
483                   rs2_name, s_imm, rs1_name);
484       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
485       sim_core_write_unaligned_8 (cpu, cpu->pc, write_map,
486                                   cpu->regs[rs1] + s_imm, cpu->regs[rs2]);
487       break;
488     case MATCH_SW:
489       TRACE_INSN (cpu, "sw %s, %" PRIiTW "(%s);",
490                   rs2_name, s_imm, rs1_name);
491       sim_core_write_unaligned_4 (cpu, cpu->pc, write_map,
492                                   cpu->regs[rs1] + s_imm, cpu->regs[rs2]);
493       break;
494     case MATCH_SH:
495       TRACE_INSN (cpu, "sh %s, %" PRIiTW "(%s);",
496                   rs2_name, s_imm, rs1_name);
497       sim_core_write_unaligned_2 (cpu, cpu->pc, write_map,
498                                   cpu->regs[rs1] + s_imm, cpu->regs[rs2]);
499       break;
500     case MATCH_SB:
501       TRACE_INSN (cpu, "sb %s, %" PRIiTW "(%s);",
502                   rs2_name, s_imm, rs1_name);
503       sim_core_write_unaligned_1 (cpu, cpu->pc, write_map,
504                                   cpu->regs[rs1] + s_imm, cpu->regs[rs2]);
505       break;
506
507     case MATCH_CSRRC:
508       TRACE_INSN (cpu, "csrrc");
509       switch (csr)
510         {
511 #define DECLARE_CSR(name, num, ...) \
512         case num: \
513           store_rd (cpu, rd, fetch_csr (cpu, #name, num, &cpu->csr.name)); \
514           store_csr (cpu, #name, num, &cpu->csr.name, \
515                      cpu->csr.name & !cpu->regs[rs1]); \
516           break;
517 #include "opcode/riscv-opc.h"
518 #undef DECLARE_CSR
519         }
520       break;
521     case MATCH_CSRRS:
522       TRACE_INSN (cpu, "csrrs");
523       switch (csr)
524         {
525 #define DECLARE_CSR(name, num, ...) \
526         case num: \
527           store_rd (cpu, rd, fetch_csr (cpu, #name, num, &cpu->csr.name)); \
528           store_csr (cpu, #name, num, &cpu->csr.name, \
529                      cpu->csr.name | cpu->regs[rs1]); \
530           break;
531 #include "opcode/riscv-opc.h"
532 #undef DECLARE_CSR
533         }
534       break;
535     case MATCH_CSRRW:
536       TRACE_INSN (cpu, "csrrw");
537       switch (csr)
538         {
539 #define DECLARE_CSR(name, num, ...) \
540         case num: \
541           store_rd (cpu, rd, fetch_csr (cpu, #name, num, &cpu->csr.name)); \
542           store_csr (cpu, #name, num, &cpu->csr.name, cpu->regs[rs1]); \
543           break;
544 #include "opcode/riscv-opc.h"
545 #undef DECLARE_CSR
546         }
547       break;
548
549     case MATCH_RDCYCLE:
550       TRACE_INSN (cpu, "rdcycle %s;", rd_name);
551       store_rd (cpu, rd, fetch_csr (cpu, "cycle", CSR_CYCLE, &cpu->csr.cycle));
552       break;
553     case MATCH_RDCYCLEH:
554       TRACE_INSN (cpu, "rdcycleh %s;", rd_name);
555       RISCV_ASSERT_RV32 (cpu, "insn: %s", op->name);
556       store_rd (cpu, rd,
557                 fetch_csr (cpu, "cycleh", CSR_CYCLEH, &cpu->csr.cycleh));
558       break;
559     case MATCH_RDINSTRET:
560       TRACE_INSN (cpu, "rdinstret %s;", rd_name);
561       store_rd (cpu, rd,
562                 fetch_csr (cpu, "instret", CSR_INSTRET, &cpu->csr.instret));
563       break;
564     case MATCH_RDINSTRETH:
565       TRACE_INSN (cpu, "rdinstreth %s;", rd_name);
566       RISCV_ASSERT_RV32 (cpu, "insn: %s", op->name);
567       store_rd (cpu, rd,
568                 fetch_csr (cpu, "instreth", CSR_INSTRETH, &cpu->csr.instreth));
569       break;
570     case MATCH_RDTIME:
571       TRACE_INSN (cpu, "rdtime %s;", rd_name);
572       store_rd (cpu, rd, fetch_csr (cpu, "time", CSR_TIME, &cpu->csr.time));
573       break;
574     case MATCH_RDTIMEH:
575       TRACE_INSN (cpu, "rdtimeh %s;", rd_name);
576       RISCV_ASSERT_RV32 (cpu, "insn: %s", op->name);
577       store_rd (cpu, rd, fetch_csr (cpu, "timeh", CSR_TIMEH, &cpu->csr.timeh));
578       break;
579
580     case MATCH_FENCE:
581       TRACE_INSN (cpu, "fence;");
582       break;
583     case MATCH_FENCE_I:
584       TRACE_INSN (cpu, "fence.i;");
585       break;
586     case MATCH_EBREAK:
587       TRACE_INSN (cpu, "ebreak;");
588       /* GDB expects us to step over EBREAK.  */
589       sim_engine_halt (sd, cpu, NULL, cpu->pc + 4, sim_stopped, SIM_SIGTRAP);
590       break;
591     case MATCH_ECALL:
592       TRACE_INSN (cpu, "ecall;");
593       cpu->a0 = sim_syscall (cpu, cpu->a7, cpu->a0, cpu->a1, cpu->a2, cpu->a3);
594       break;
595     default:
596       TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
597       sim_engine_halt (sd, cpu, NULL, cpu->pc, sim_signalled, SIM_SIGILL);
598     }
599
600   return pc;
601 }
602
603 static uint64_t
604 mulhu (uint64_t a, uint64_t b)
605 {
606 #ifdef HAVE___INT128
607   return ((__int128)a * b) >> 64;
608 #else
609   uint64_t t;
610   uint32_t y1, y2, y3;
611   uint64_t a0 = (uint32_t)a, a1 = a >> 32;
612   uint64_t b0 = (uint32_t)b, b1 = b >> 32;
613
614   t = a1*b0 + ((a0*b0) >> 32);
615   y1 = t;
616   y2 = t >> 32;
617
618   t = a0*b1 + y1;
619   y1 = t;
620
621   t = a1*b1 + y2 + (t >> 32);
622   y2 = t;
623   y3 = t >> 32;
624
625   return ((uint64_t)y3 << 32) | y2;
626 #endif
627 }
628
629 static uint64_t
630 mulh (int64_t a, int64_t b)
631 {
632   int negate = (a < 0) != (b < 0);
633   uint64_t res = mulhu (a < 0 ? -a : a, b < 0 ? -b : b);
634   return negate ? ~res + (a * b == 0) : res;
635 }
636
637 static uint64_t
638 mulhsu (int64_t a, uint64_t b)
639 {
640   int negate = a < 0;
641   uint64_t res = mulhu (a < 0 ? -a : a, b);
642   return negate ? ~res + (a * b == 0) : res;
643 }
644
645 static sim_cia
646 execute_m (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
647 {
648   SIM_DESC sd = CPU_STATE (cpu);
649   int rd = (iw >> OP_SH_RD) & OP_MASK_RD;
650   int rs1 = (iw >> OP_SH_RS1) & OP_MASK_RS1;
651   int rs2 = (iw >> OP_SH_RS2) & OP_MASK_RS2;
652   const char *rd_name = riscv_gpr_names_abi[rd];
653   const char *rs1_name = riscv_gpr_names_abi[rs1];
654   const char *rs2_name = riscv_gpr_names_abi[rs2];
655   unsigned_word tmp, dividend_max;
656   sim_cia pc = cpu->pc + 4;
657
658   dividend_max = -((unsigned_word) 1 << (WITH_TARGET_WORD_BITSIZE - 1));
659
660   switch (op->match)
661     {
662     case MATCH_DIV:
663       TRACE_INSN (cpu, "div %s, %s, %s;  // %s = %s / %s",
664                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
665       if (cpu->regs[rs1] == dividend_max && cpu->regs[rs2] == -1)
666         tmp = dividend_max;
667       else if (cpu->regs[rs2])
668         tmp = (signed_word) cpu->regs[rs1] / (signed_word) cpu->regs[rs2];
669       else
670         tmp = -1;
671       store_rd (cpu, rd, tmp);
672       break;
673     case MATCH_DIVW:
674       TRACE_INSN (cpu, "divw %s, %s, %s;  // %s = %s / %s",
675                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
676       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
677       if (EXTEND32 (cpu->regs[rs2]) == -1)
678         tmp = 1 << 31;
679       else if (EXTEND32 (cpu->regs[rs2]))
680         tmp = EXTEND32 (cpu->regs[rs1]) / EXTEND32 (cpu->regs[rs2]);
681       else
682         tmp = -1;
683       store_rd (cpu, rd, EXTEND32 (tmp));
684       break;
685     case MATCH_DIVU:
686       TRACE_INSN (cpu, "divu %s, %s, %s;  // %s = %s / %s",
687                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
688       if (cpu->regs[rs2])
689         store_rd (cpu, rd, (unsigned_word) cpu->regs[rs1]
690                            / (unsigned_word) cpu->regs[rs2]);
691       else
692         store_rd (cpu, rd, -1);
693       break;
694     case MATCH_DIVUW:
695       TRACE_INSN (cpu, "divuw %s, %s, %s;  // %s = %s / %s",
696                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
697       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
698       if ((uint32_t) cpu->regs[rs2])
699         tmp = (uint32_t) cpu->regs[rs1] / (uint32_t) cpu->regs[rs2];
700       else
701         tmp = -1;
702       store_rd (cpu, rd, EXTEND32 (tmp));
703       break;
704     case MATCH_MUL:
705       TRACE_INSN (cpu, "mul %s, %s, %s;  // %s = %s * %s",
706                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
707       store_rd (cpu, rd, cpu->regs[rs1] * cpu->regs[rs2]);
708       break;
709     case MATCH_MULW:
710       TRACE_INSN (cpu, "mulw %s, %s, %s;  // %s = %s * %s",
711                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
712       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
713       store_rd (cpu, rd, EXTEND32 ((int32_t) cpu->regs[rs1]
714                                    * (int32_t) cpu->regs[rs2]));
715       break;
716     case MATCH_MULH:
717       TRACE_INSN (cpu, "mulh %s, %s, %s;  // %s = %s * %s",
718                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
719       if (RISCV_XLEN (cpu) == 32)
720         store_rd (cpu, rd, ((int64_t)(signed_word) cpu->regs[rs1]
721                             * (int64_t)(signed_word) cpu->regs[rs2]) >> 32);
722       else
723         store_rd (cpu, rd, mulh (cpu->regs[rs1], cpu->regs[rs2]));
724       break;
725     case MATCH_MULHU:
726       TRACE_INSN (cpu, "mulhu %s, %s, %s;  // %s = %s * %s",
727                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
728       if (RISCV_XLEN (cpu) == 32)
729         store_rd (cpu, rd, ((uint64_t)cpu->regs[rs1]
730                             * (uint64_t)cpu->regs[rs2]) >> 32);
731       else
732         store_rd (cpu, rd, mulhu (cpu->regs[rs1], cpu->regs[rs2]));
733       break;
734     case MATCH_MULHSU:
735       TRACE_INSN (cpu, "mulhsu %s, %s, %s;  // %s = %s * %s",
736                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
737       if (RISCV_XLEN (cpu) == 32)
738         store_rd (cpu, rd, ((int64_t)(signed_word) cpu->regs[rs1]
739                             * (uint64_t)cpu->regs[rs2]) >> 32);
740       else
741         store_rd (cpu, rd, mulhsu (cpu->regs[rs1], cpu->regs[rs2]));
742       break;
743     case MATCH_REM:
744       TRACE_INSN (cpu, "rem %s, %s, %s;  // %s = %s %% %s",
745                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
746       if (cpu->regs[rs1] == dividend_max && cpu->regs[rs2] == -1)
747         tmp = 0;
748       else if (cpu->regs[rs2])
749         tmp = (signed_word) cpu->regs[rs1] % (signed_word) cpu->regs[rs2];
750       else
751         tmp = cpu->regs[rs1];
752       store_rd (cpu, rd, tmp);
753       break;
754     case MATCH_REMW:
755       TRACE_INSN (cpu, "remw %s, %s, %s;  // %s = %s %% %s",
756                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
757       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
758       if (EXTEND32 (cpu->regs[rs2]) == -1)
759         tmp = 0;
760       else if (EXTEND32 (cpu->regs[rs2]))
761         tmp = EXTEND32 (cpu->regs[rs1]) % EXTEND32 (cpu->regs[rs2]);
762       else
763         tmp = cpu->regs[rs1];
764       store_rd (cpu, rd, EXTEND32 (tmp));
765       break;
766     case MATCH_REMU:
767       TRACE_INSN (cpu, "remu %s, %s, %s;  // %s = %s %% %s",
768                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
769       if (cpu->regs[rs2])
770         store_rd (cpu, rd, cpu->regs[rs1] % cpu->regs[rs2]);
771       else
772         store_rd (cpu, rd, cpu->regs[rs1]);
773       break;
774     case MATCH_REMUW:
775       TRACE_INSN (cpu, "remuw %s, %s, %s;  // %s = %s %% %s",
776                   rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
777       RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
778       if ((uint32_t) cpu->regs[rs2])
779         tmp = (uint32_t) cpu->regs[rs1] % (uint32_t) cpu->regs[rs2];
780       else
781         tmp = cpu->regs[rs1];
782       store_rd (cpu, rd, EXTEND32 (tmp));
783       break;
784     default:
785       TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
786       sim_engine_halt (sd, cpu, NULL, cpu->pc, sim_signalled, SIM_SIGILL);
787     }
788
789   return pc;
790 }
791
792 static sim_cia
793 execute_a (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
794 {
795   SIM_DESC sd = CPU_STATE (cpu);
796   struct riscv_sim_state *state = RISCV_SIM_STATE (sd);
797   int rd = (iw >> OP_SH_RD) & OP_MASK_RD;
798   int rs1 = (iw >> OP_SH_RS1) & OP_MASK_RS1;
799   int rs2 = (iw >> OP_SH_RS2) & OP_MASK_RS2;
800   const char *rd_name = riscv_gpr_names_abi[rd];
801   const char *rs1_name = riscv_gpr_names_abi[rs1];
802   const char *rs2_name = riscv_gpr_names_abi[rs2];
803   struct atomic_mem_reserved_list *amo_prev, *amo_curr;
804   unsigned_word tmp;
805   sim_cia pc = cpu->pc + 4;
806
807   /* Handle these two load/store operations specifically.  */
808   switch (op->match)
809     {
810     case MATCH_LR_W:
811       TRACE_INSN (cpu, "%s %s, (%s);", op->name, rd_name, rs1_name);
812       store_rd (cpu, rd,
813         sim_core_read_unaligned_4 (cpu, cpu->pc, read_map, cpu->regs[rs1]));
814
815       /* Walk the reservation list to find an existing match.  */
816       amo_curr = state->amo_reserved_list;
817       while (amo_curr)
818         {
819           if (amo_curr->addr == cpu->regs[rs1])
820             goto done;
821           amo_curr = amo_curr->next;
822         }
823
824       /* No reservation exists, so add one.  */
825       amo_curr = xmalloc (sizeof (*amo_curr));
826       amo_curr->addr = cpu->regs[rs1];
827       amo_curr->next = state->amo_reserved_list;
828       state->amo_reserved_list = amo_curr;
829       goto done;
830     case MATCH_SC_W:
831       TRACE_INSN (cpu, "%s %s, %s, (%s);", op->name, rd_name, rs2_name,
832                   rs1_name);
833
834       /* Walk the reservation list to find a match.  */
835       amo_curr = amo_prev = state->amo_reserved_list;
836       while (amo_curr)
837         {
838           if (amo_curr->addr == cpu->regs[rs1])
839             {
840               /* We found a reservation, so operate it.  */
841               sim_core_write_unaligned_4 (cpu, cpu->pc, write_map,
842                                           cpu->regs[rs1], cpu->regs[rs2]);
843               store_rd (cpu, rd, 0);
844               if (amo_curr == state->amo_reserved_list)
845                 state->amo_reserved_list = amo_curr->next;
846               else
847                 amo_prev->next = amo_curr->next;
848               free (amo_curr);
849               goto done;
850             }
851           amo_prev = amo_curr;
852           amo_curr = amo_curr->next;
853         }
854
855       /* If we're still here, then no reservation exists, so mark as failed.  */
856       store_rd (cpu, rd, 1);
857       goto done;
858     }
859
860   /* Handle the rest of the atomic insns with common code paths.  */
861   TRACE_INSN (cpu, "%s %s, %s, (%s);",
862               op->name, rd_name, rs2_name, rs1_name);
863   if (op->xlen_requirement == 64)
864     tmp = sim_core_read_unaligned_8 (cpu, cpu->pc, read_map, cpu->regs[rs1]);
865   else
866     tmp = EXTEND32 (sim_core_read_unaligned_4 (cpu, cpu->pc, read_map,
867                                                cpu->regs[rs1]));
868   store_rd (cpu, rd, tmp);
869
870   switch (op->match)
871     {
872     case MATCH_AMOADD_D:
873     case MATCH_AMOADD_W:
874       tmp = cpu->regs[rd] + cpu->regs[rs2];
875       break;
876     case MATCH_AMOAND_D:
877     case MATCH_AMOAND_W:
878       tmp = cpu->regs[rd] & cpu->regs[rs2];
879       break;
880     case MATCH_AMOMAX_D:
881     case MATCH_AMOMAX_W:
882       tmp = max ((signed_word) cpu->regs[rd], (signed_word) cpu->regs[rs2]);
883       break;
884     case MATCH_AMOMAXU_D:
885     case MATCH_AMOMAXU_W:
886       tmp = max ((unsigned_word) cpu->regs[rd], (unsigned_word) cpu->regs[rs2]);
887       break;
888     case MATCH_AMOMIN_D:
889     case MATCH_AMOMIN_W:
890       tmp = min ((signed_word) cpu->regs[rd], (signed_word) cpu->regs[rs2]);
891       break;
892     case MATCH_AMOMINU_D:
893     case MATCH_AMOMINU_W:
894       tmp = min ((unsigned_word) cpu->regs[rd], (unsigned_word) cpu->regs[rs2]);
895       break;
896     case MATCH_AMOOR_D:
897     case MATCH_AMOOR_W:
898       tmp = cpu->regs[rd] | cpu->regs[rs2];
899       break;
900     case MATCH_AMOSWAP_D:
901     case MATCH_AMOSWAP_W:
902       tmp = cpu->regs[rs2];
903       break;
904     case MATCH_AMOXOR_D:
905     case MATCH_AMOXOR_W:
906       tmp = cpu->regs[rd] ^ cpu->regs[rs2];
907       break;
908     default:
909       TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
910       sim_engine_halt (sd, cpu, NULL, cpu->pc, sim_signalled, SIM_SIGILL);
911     }
912
913   if (op->xlen_requirement == 64)
914     sim_core_write_unaligned_8 (cpu, cpu->pc, write_map, cpu->regs[rs1], tmp);
915   else
916     sim_core_write_unaligned_4 (cpu, cpu->pc, write_map, cpu->regs[rs1], tmp);
917
918  done:
919   return pc;
920 }
921
922 static sim_cia
923 execute_one (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
924 {
925   SIM_DESC sd = CPU_STATE (cpu);
926
927   if (op->xlen_requirement == 32)
928     RISCV_ASSERT_RV32 (cpu, "insn: %s", op->name);
929   else if (op->xlen_requirement == 64)
930     RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
931
932   switch (op->insn_class)
933     {
934     case INSN_CLASS_A:
935       return execute_a (cpu, iw, op);
936     case INSN_CLASS_I:
937       return execute_i (cpu, iw, op);
938     case INSN_CLASS_M:
939     case INSN_CLASS_ZMMUL:
940       return execute_m (cpu, iw, op);
941     default:
942       TRACE_INSN (cpu, "UNHANDLED EXTENSION: %d", op->insn_class);
943       sim_engine_halt (sd, cpu, NULL, cpu->pc, sim_signalled, SIM_SIGILL);
944     }
945
946   return cpu->pc + riscv_insn_length (iw);
947 }
948
949 /* Decode & execute a single instruction.  */
950 void step_once (SIM_CPU *cpu)
951 {
952   SIM_DESC sd = CPU_STATE (cpu);
953   unsigned_word iw;
954   unsigned int len;
955   sim_cia pc = cpu->pc;
956   const struct riscv_opcode *op;
957   int xlen = RISCV_XLEN (cpu);
958
959   if (TRACE_ANY_P (cpu))
960     trace_prefix (sd, cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu),
961                   NULL, 0, " "); /* Use a space for gcc warnings.  */
962
963   iw = sim_core_read_aligned_2 (cpu, pc, exec_map, pc);
964
965   /* Reject non-32-bit opcodes first.  */
966   len = riscv_insn_length (iw);
967   if (len != 4)
968     {
969       sim_io_printf (sd, "sim: bad insn len %#x @ %#" PRIxTA ": %#" PRIxTW "\n",
970                      len, pc, iw);
971       sim_engine_halt (sd, cpu, NULL, pc, sim_signalled, SIM_SIGILL);
972     }
973
974   iw |= ((unsigned_word) sim_core_read_aligned_2 (
975     cpu, pc, exec_map, pc + 2) << 16);
976
977   TRACE_CORE (cpu, "0x%08" PRIxTW, iw);
978
979   op = riscv_hash[OP_HASH_IDX (iw)];
980   if (!op)
981     sim_engine_halt (sd, cpu, NULL, pc, sim_signalled, SIM_SIGILL);
982
983   /* NB: Same loop logic as riscv_disassemble_insn.  */
984   for (; op->name; op++)
985     {
986       /* Does the opcode match?  */
987       if (! op->match_func (op, iw))
988         continue;
989       /* Is this a pseudo-instruction and may we print it as such?  */
990       if (op->pinfo & INSN_ALIAS)
991         continue;
992       /* Is this instruction restricted to a certain value of XLEN?  */
993       if (op->xlen_requirement != 0 && op->xlen_requirement != xlen)
994         continue;
995
996       /* It's a match.  */
997       pc = execute_one (cpu, iw, op);
998       break;
999     }
1000
1001   /* TODO: Handle overflow into high 32 bits.  */
1002   /* TODO: Try to use a common counter and only update on demand (reads).  */
1003   ++cpu->csr.cycle;
1004   ++cpu->csr.instret;
1005
1006   cpu->pc = pc;
1007 }
1008 \f
1009 /* Return the program counter for this cpu. */
1010 static sim_cia
1011 pc_get (sim_cpu *cpu)
1012 {
1013   return cpu->pc;
1014 }
1015
1016 /* Set the program counter for this cpu to the new pc value. */
1017 static void
1018 pc_set (sim_cpu *cpu, sim_cia pc)
1019 {
1020   cpu->pc = pc;
1021 }
1022
1023 static int
1024 reg_fetch (sim_cpu *cpu, int rn, void *buf, int len)
1025 {
1026   if (len <= 0 || len > sizeof (unsigned_word))
1027     return -1;
1028
1029   switch (rn)
1030     {
1031     case SIM_RISCV_ZERO_REGNUM:
1032       memset (buf, 0, len);
1033       return len;
1034     case SIM_RISCV_RA_REGNUM ... SIM_RISCV_T6_REGNUM:
1035       memcpy (buf, &cpu->regs[rn], len);
1036       return len;
1037     case SIM_RISCV_FIRST_FP_REGNUM ... SIM_RISCV_LAST_FP_REGNUM:
1038       memcpy (buf, &cpu->fpregs[rn - SIM_RISCV_FIRST_FP_REGNUM], len);
1039       return len;
1040     case SIM_RISCV_PC_REGNUM:
1041       memcpy (buf, &cpu->pc, len);
1042       return len;
1043
1044 #define DECLARE_CSR(name, num, ...) \
1045     case SIM_RISCV_ ## num ## _REGNUM: \
1046       memcpy (buf, &cpu->csr.name, len); \
1047       return len;
1048 #include "opcode/riscv-opc.h"
1049 #undef DECLARE_CSR
1050
1051     default:
1052       return -1;
1053     }
1054 }
1055
1056 static int
1057 reg_store (sim_cpu *cpu, int rn, const void *buf, int len)
1058 {
1059   if (len <= 0 || len > sizeof (unsigned_word))
1060     return -1;
1061
1062   switch (rn)
1063     {
1064     case SIM_RISCV_ZERO_REGNUM:
1065       /* Ignore writes.  */
1066       return len;
1067     case SIM_RISCV_RA_REGNUM ... SIM_RISCV_T6_REGNUM:
1068       memcpy (&cpu->regs[rn], buf, len);
1069       return len;
1070     case SIM_RISCV_FIRST_FP_REGNUM ... SIM_RISCV_LAST_FP_REGNUM:
1071       memcpy (&cpu->fpregs[rn - SIM_RISCV_FIRST_FP_REGNUM], buf, len);
1072       return len;
1073     case SIM_RISCV_PC_REGNUM:
1074       memcpy (&cpu->pc, buf, len);
1075       return len;
1076
1077 #define DECLARE_CSR(name, num, ...) \
1078     case SIM_RISCV_ ## num ## _REGNUM: \
1079       memcpy (&cpu->csr.name, buf, len); \
1080       return len;
1081 #include "opcode/riscv-opc.h"
1082 #undef DECLARE_CSR
1083
1084     default:
1085       return -1;
1086     }
1087 }
1088
1089 /* Initialize the state for a single cpu.  Usuaully this involves clearing all
1090    registers back to their reset state.  Should also hook up the fetch/store
1091    helper functions too.  */
1092 void
1093 initialize_cpu (SIM_DESC sd, SIM_CPU *cpu, int mhartid)
1094 {
1095   const char *extensions;
1096   int i;
1097
1098   memset (cpu->regs, 0, sizeof (cpu->regs));
1099
1100   CPU_PC_FETCH (cpu) = pc_get;
1101   CPU_PC_STORE (cpu) = pc_set;
1102   CPU_REG_FETCH (cpu) = reg_fetch;
1103   CPU_REG_STORE (cpu) = reg_store;
1104
1105   if (!riscv_hash[0])
1106     {
1107       const struct riscv_opcode *op;
1108
1109       for (op = riscv_opcodes; op->name; op++)
1110         if (!riscv_hash[OP_HASH_IDX (op->match)])
1111           riscv_hash[OP_HASH_IDX (op->match)] = op;
1112     }
1113
1114   cpu->csr.misa = 0;
1115   /* RV32 sets this field to 0, and we don't really support RV128 yet.  */
1116   if (RISCV_XLEN (cpu) == 64)
1117     cpu->csr.misa |= (uint64_t)2 << 62;
1118
1119   /* Skip the leading "rv" prefix and the two numbers.  */
1120   extensions = MODEL_NAME (CPU_MODEL (cpu)) + 4;
1121   for (i = 0; i < 26; ++i)
1122     {
1123       char ext = 'A' + i;
1124
1125       if (ext == 'X')
1126         continue;
1127       else if (strchr (extensions, ext) != NULL)
1128         {
1129           if (ext == 'G')
1130             cpu->csr.misa |= 0x1129;  /* G = IMAFD.  */
1131           else
1132             cpu->csr.misa |= (1 << i);
1133         }
1134     }
1135
1136   cpu->csr.mimpid = 0x8000;
1137   cpu->csr.mhartid = mhartid;
1138 }
1139 \f
1140 /* Some utils don't like having a NULL environ.  */
1141 static const char * const simple_env[] = { "HOME=/", "PATH=/bin", NULL };
1142
1143 /* Count the number of arguments in an argv.  */
1144 static int
1145 count_argv (const char * const *argv)
1146 {
1147   int i;
1148
1149   if (!argv)
1150     return -1;
1151
1152   for (i = 0; argv[i] != NULL; ++i)
1153     continue;
1154   return i;
1155 }
1156
1157 void
1158 initialize_env (SIM_DESC sd, const char * const *argv, const char * const *env)
1159 {
1160   SIM_CPU *cpu = STATE_CPU (sd, 0);
1161   int i;
1162   int argc, argv_flat;
1163   int envc, env_flat;
1164   address_word sp, sp_flat;
1165   unsigned char null[8] = { 0, 0, 0, 0, 0, 0, 0, 0, };
1166
1167   /* Figure out how many bytes the argv strings take up.  */
1168   argc = count_argv (argv);
1169   if (argc == -1)
1170     argc = 0;
1171   argv_flat = argc; /* NUL bytes.  */
1172   for (i = 0; i < argc; ++i)
1173     argv_flat += strlen (argv[i]);
1174
1175   /* Figure out how many bytes the environ strings take up.  */
1176   if (!env)
1177     env = simple_env;
1178   envc = count_argv (env);
1179   env_flat = envc; /* NUL bytes.  */
1180   for (i = 0; i < envc; ++i)
1181     env_flat += strlen (env[i]);
1182
1183   /* Make space for the strings themselves.  */
1184   sp_flat = (DEFAULT_MEM_SIZE - argv_flat - env_flat) & -sizeof (address_word);
1185   /* Then the pointers to the strings.  */
1186   sp = sp_flat - ((argc + 1 + envc + 1) * sizeof (address_word));
1187   /* Then the argc.  */
1188   sp -= sizeof (unsigned_word);
1189
1190   /* Set up the regs the libgloss crt0 expects.  */
1191   cpu->a0 = argc;
1192   cpu->sp = sp;
1193
1194   /* First push the argc value.  */
1195   sim_write (sd, sp, &argc, sizeof (unsigned_word));
1196   sp += sizeof (unsigned_word);
1197
1198   /* Then the actual argv strings so we know where to point argv[].  */
1199   for (i = 0; i < argc; ++i)
1200     {
1201       unsigned len = strlen (argv[i]) + 1;
1202       sim_write (sd, sp_flat, argv[i], len);
1203       sim_write (sd, sp, &sp_flat, sizeof (address_word));
1204       sp_flat += len;
1205       sp += sizeof (address_word);
1206     }
1207   sim_write (sd, sp, null, sizeof (address_word));
1208   sp += sizeof (address_word);
1209
1210   /* Then the actual env strings so we know where to point env[].  */
1211   for (i = 0; i < envc; ++i)
1212     {
1213       unsigned len = strlen (env[i]) + 1;
1214       sim_write (sd, sp_flat, env[i], len);
1215       sim_write (sd, sp, &sp_flat, sizeof (address_word));
1216       sp_flat += len;
1217       sp += sizeof (address_word);
1218     }
1219 }
This page took 0.091897 seconds and 4 git commands to generate.