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