gdb/testsuite: Reduce gdb.threads/threadcrash.exp reliance on libc symbols
[binutils-gdb.git] / sim / riscv / sim-main.c
blobadff99921c65fd2ede0a411572d0ee10ed0aa9f8
1 /* RISC-V simulator.
3 Copyright (C) 2005-2024 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 TRACE_INSN (cpu, "RV32I-only " fmt, ## args); \
52 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, sim_pc_get (cpu), \
53 sim_signalled, SIM_SIGILL); \
54 } \
55 } while (0)
57 #define RISCV_ASSERT_RV64(cpu, fmt, args...) \
58 do { \
59 if (RISCV_XLEN (cpu) != 64) \
60 { \
61 TRACE_INSN (cpu, "RV64I-only " fmt, ## args); \
62 sim_engine_halt (CPU_STATE (cpu), cpu, NULL, sim_pc_get (cpu), \
63 sim_signalled, SIM_SIGILL); \
64 } \
65 } while (0)
67 static INLINE void
68 store_rd (SIM_CPU *cpu, int rd, unsigned_word val)
70 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
72 if (rd)
74 riscv_cpu->regs[rd] = val;
75 TRACE_REG (cpu, rd);
79 static INLINE unsigned_word
80 fetch_csr (SIM_CPU *cpu, const char *name, int csr, unsigned_word *reg)
82 /* Handle pseudo registers. */
83 switch (csr)
85 /* Allow certain registers only in respective modes. */
86 case CSR_CYCLEH:
87 case CSR_INSTRETH:
88 case CSR_TIMEH:
89 RISCV_ASSERT_RV32 (cpu, "CSR: %s", name);
90 break;
93 return *reg;
96 static INLINE void
97 store_csr (SIM_CPU *cpu, const char *name, int csr, unsigned_word *reg,
98 unsigned_word val)
100 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
102 switch (csr)
104 /* These are pseudo registers that modify sub-fields of fcsr. */
105 case CSR_FRM:
106 val &= 0x7;
107 *reg = val;
108 riscv_cpu->csr.fcsr = (riscv_cpu->csr.fcsr & ~0xe0) | (val << 5);
109 break;
110 case CSR_FFLAGS:
111 val &= 0x1f;
112 *reg = val;
113 riscv_cpu->csr.fcsr = (riscv_cpu->csr.fcsr & ~0x1f) | val;
114 break;
115 /* Keep the sub-fields in sync. */
116 case CSR_FCSR:
117 *reg = val;
118 riscv_cpu->csr.frm = (val >> 5) & 0x7;
119 riscv_cpu->csr.fflags = val & 0x1f;
120 break;
122 /* Allow certain registers only in respective modes. */
123 case CSR_CYCLEH:
124 case CSR_INSTRETH:
125 case CSR_TIMEH:
126 RISCV_ASSERT_RV32 (cpu, "CSR: %s", name);
127 ATTRIBUTE_FALLTHROUGH;
129 /* All the rest are immutable. */
130 default:
131 val = *reg;
132 break;
135 TRACE_REGISTER (cpu, "wrote CSR %s = %#" PRIxTW, name, val);
138 static inline unsigned_word
139 ashiftrt (unsigned_word val, unsigned_word shift)
141 uint32_t sign = (val & 0x80000000) ? ~(0xfffffffful >> shift) : 0;
142 return (val >> shift) | sign;
145 static inline unsigned_word
146 ashiftrt64 (unsigned_word val, unsigned_word shift)
148 uint64_t sign =
149 (val & 0x8000000000000000ull) ? ~(0xffffffffffffffffull >> shift) : 0;
150 return (val >> shift) | sign;
153 static sim_cia
154 execute_i (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
156 SIM_DESC sd = CPU_STATE (cpu);
157 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
158 int rd = (iw >> OP_SH_RD) & OP_MASK_RD;
159 int rs1 = (iw >> OP_SH_RS1) & OP_MASK_RS1;
160 int rs2 = (iw >> OP_SH_RS2) & OP_MASK_RS2;
161 const char *rd_name = riscv_gpr_names_abi[rd];
162 const char *rs1_name = riscv_gpr_names_abi[rs1];
163 const char *rs2_name = riscv_gpr_names_abi[rs2];
164 unsigned int csr = (iw >> OP_SH_CSR) & OP_MASK_CSR;
165 unsigned_word i_imm = EXTRACT_ITYPE_IMM (iw);
166 unsigned_word u_imm = EXTRACT_UTYPE_IMM ((uint64_t) iw);
167 unsigned_word s_imm = EXTRACT_STYPE_IMM (iw);
168 unsigned_word sb_imm = EXTRACT_BTYPE_IMM (iw);
169 unsigned_word shamt_imm = ((iw >> OP_SH_SHAMT) & OP_MASK_SHAMT);
170 unsigned_word tmp;
171 sim_cia pc = riscv_cpu->pc + 4;
173 TRACE_EXTRACT (cpu,
174 "rd:%-2i:%-4s "
175 "rs1:%-2i:%-4s %0*" PRIxTW " "
176 "rs2:%-2i:%-4s %0*" PRIxTW " "
177 "match:%#x mask:%#x",
178 rd, rd_name,
179 rs1, rs1_name, (int) sizeof (unsigned_word) * 2,
180 riscv_cpu->regs[rs1],
181 rs2, rs2_name, (int) sizeof (unsigned_word) * 2,
182 riscv_cpu->regs[rs2],
183 (unsigned) op->match, (unsigned) op->mask);
185 switch (op->match)
187 case MATCH_ADD:
188 TRACE_INSN (cpu, "add %s, %s, %s; // %s = %s + %s",
189 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
190 store_rd (cpu, rd, riscv_cpu->regs[rs1] + riscv_cpu->regs[rs2]);
191 break;
192 case MATCH_ADDW:
193 TRACE_INSN (cpu, "addw %s, %s, %s; // %s = %s + %s",
194 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
195 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
196 store_rd (cpu, rd,
197 EXTEND32 (riscv_cpu->regs[rs1] + riscv_cpu->regs[rs2]));
198 break;
199 case MATCH_ADDI:
200 TRACE_INSN (cpu, "addi %s, %s, %#" PRIxTW "; // %s = %s + %#" PRIxTW,
201 rd_name, rs1_name, i_imm, rd_name, rs1_name, i_imm);
202 store_rd (cpu, rd, riscv_cpu->regs[rs1] + i_imm);
203 break;
204 case MATCH_ADDIW:
205 TRACE_INSN (cpu, "addiw %s, %s, %#" PRIxTW "; // %s = %s + %#" PRIxTW,
206 rd_name, rs1_name, i_imm, rd_name, rs1_name, i_imm);
207 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
208 store_rd (cpu, rd, EXTEND32 (riscv_cpu->regs[rs1] + i_imm));
209 break;
210 case MATCH_AND:
211 TRACE_INSN (cpu, "and %s, %s, %s; // %s = %s & %s",
212 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
213 store_rd (cpu, rd, riscv_cpu->regs[rs1] & riscv_cpu->regs[rs2]);
214 break;
215 case MATCH_ANDI:
216 TRACE_INSN (cpu, "andi %s, %s, %" PRIiTW "; // %s = %s & %#" PRIxTW,
217 rd_name, rs1_name, i_imm, rd_name, rs1_name, i_imm);
218 store_rd (cpu, rd, riscv_cpu->regs[rs1] & i_imm);
219 break;
220 case MATCH_OR:
221 TRACE_INSN (cpu, "or %s, %s, %s; // %s = %s | %s",
222 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
223 store_rd (cpu, rd, riscv_cpu->regs[rs1] | riscv_cpu->regs[rs2]);
224 break;
225 case MATCH_ORI:
226 TRACE_INSN (cpu, "ori %s, %s, %" PRIiTW "; // %s = %s | %#" PRIxTW,
227 rd_name, rs1_name, i_imm, rd_name, rs1_name, i_imm);
228 store_rd (cpu, rd, riscv_cpu->regs[rs1] | i_imm);
229 break;
230 case MATCH_XOR:
231 TRACE_INSN (cpu, "xor %s, %s, %s; // %s = %s ^ %s",
232 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
233 store_rd (cpu, rd, riscv_cpu->regs[rs1] ^ riscv_cpu->regs[rs2]);
234 break;
235 case MATCH_XORI:
236 TRACE_INSN (cpu, "xori %s, %s, %" PRIiTW "; // %s = %s ^ %#" PRIxTW,
237 rd_name, rs1_name, i_imm, rd_name, rs1_name, i_imm);
238 store_rd (cpu, rd, riscv_cpu->regs[rs1] ^ i_imm);
239 break;
240 case MATCH_SUB:
241 TRACE_INSN (cpu, "sub %s, %s, %s; // %s = %s - %s",
242 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
243 store_rd (cpu, rd, riscv_cpu->regs[rs1] - riscv_cpu->regs[rs2]);
244 break;
245 case MATCH_SUBW:
246 TRACE_INSN (cpu, "subw %s, %s, %s; // %s = %s - %s",
247 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
248 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
249 store_rd (cpu, rd,
250 EXTEND32 (riscv_cpu->regs[rs1] - riscv_cpu->regs[rs2]));
251 break;
252 case MATCH_LUI:
253 TRACE_INSN (cpu, "lui %s, %#" PRIxTW ";", rd_name, u_imm);
254 store_rd (cpu, rd, u_imm);
255 break;
256 case MATCH_SLL:
257 TRACE_INSN (cpu, "sll %s, %s, %s; // %s = %s << %s",
258 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
259 u_imm = RISCV_XLEN (cpu) == 32 ? 0x1f : 0x3f;
260 store_rd (cpu, rd,
261 riscv_cpu->regs[rs1] << (riscv_cpu->regs[rs2] & u_imm));
262 break;
263 case MATCH_SLLW:
264 TRACE_INSN (cpu, "sllw %s, %s, %s; // %s = %s << %s",
265 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
266 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
267 store_rd (cpu, rd, EXTEND32 (
268 (uint32_t) riscv_cpu->regs[rs1] << (riscv_cpu->regs[rs2] & 0x1f)));
269 break;
270 case MATCH_SLLI:
271 TRACE_INSN (cpu, "slli %s, %s, %" PRIiTW "; // %s = %s << %#" PRIxTW,
272 rd_name, rs1_name, shamt_imm, rd_name, rs1_name, shamt_imm);
273 if (RISCV_XLEN (cpu) == 32 && shamt_imm > 0x1f)
274 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
275 SIM_SIGILL);
276 store_rd (cpu, rd, riscv_cpu->regs[rs1] << shamt_imm);
277 break;
278 case MATCH_SLLIW:
279 TRACE_INSN (cpu, "slliw %s, %s, %" PRIiTW "; // %s = %s << %#" PRIxTW,
280 rd_name, rs1_name, shamt_imm, rd_name, rs1_name, shamt_imm);
281 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
282 store_rd (cpu, rd,
283 EXTEND32 ((uint32_t) riscv_cpu->regs[rs1] << shamt_imm));
284 break;
285 case MATCH_SRL:
286 TRACE_INSN (cpu, "srl %s, %s, %s; // %s = %s >> %s",
287 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
288 u_imm = RISCV_XLEN (cpu) == 32 ? 0x1f : 0x3f;
289 store_rd (cpu, rd,
290 riscv_cpu->regs[rs1] >> (riscv_cpu->regs[rs2] & u_imm));
291 break;
292 case MATCH_SRLW:
293 TRACE_INSN (cpu, "srlw %s, %s, %s; // %s = %s >> %s",
294 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
295 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
296 store_rd (cpu, rd, EXTEND32 (
297 (uint32_t) riscv_cpu->regs[rs1] >> (riscv_cpu->regs[rs2] & 0x1f)));
298 break;
299 case MATCH_SRLI:
300 TRACE_INSN (cpu, "srli %s, %s, %" PRIiTW "; // %s = %s >> %#" PRIxTW,
301 rd_name, rs1_name, shamt_imm, rd_name, rs1_name, shamt_imm);
302 if (RISCV_XLEN (cpu) == 32 && shamt_imm > 0x1f)
303 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
304 SIM_SIGILL);
305 store_rd (cpu, rd, riscv_cpu->regs[rs1] >> shamt_imm);
306 break;
307 case MATCH_SRLIW:
308 TRACE_INSN (cpu, "srliw %s, %s, %" PRIiTW "; // %s = %s >> %#" PRIxTW,
309 rd_name, rs1_name, shamt_imm, rd_name, rs1_name, shamt_imm);
310 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
311 store_rd (cpu, rd,
312 EXTEND32 ((uint32_t) riscv_cpu->regs[rs1] >> shamt_imm));
313 break;
314 case MATCH_SRA:
315 TRACE_INSN (cpu, "sra %s, %s, %s; // %s = %s >>> %s",
316 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
317 if (RISCV_XLEN (cpu) == 32)
318 tmp = ashiftrt (riscv_cpu->regs[rs1], riscv_cpu->regs[rs2] & 0x1f);
319 else
320 tmp = ashiftrt64 (riscv_cpu->regs[rs1], riscv_cpu->regs[rs2] & 0x3f);
321 store_rd (cpu, rd, tmp);
322 break;
323 case MATCH_SRAW:
324 TRACE_INSN (cpu, "sraw %s, %s, %s; // %s = %s >>> %s",
325 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
326 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
327 store_rd (cpu, rd, EXTEND32 (
328 ashiftrt ((int32_t) riscv_cpu->regs[rs1],
329 riscv_cpu->regs[rs2] & 0x1f)));
330 break;
331 case MATCH_SRAI:
332 TRACE_INSN (cpu, "srai %s, %s, %" PRIiTW "; // %s = %s >>> %#" PRIxTW,
333 rd_name, rs1_name, shamt_imm, rd_name, rs1_name, shamt_imm);
334 if (RISCV_XLEN (cpu) == 32)
336 if (shamt_imm > 0x1f)
337 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
338 SIM_SIGILL);
339 tmp = ashiftrt (riscv_cpu->regs[rs1], shamt_imm);
341 else
342 tmp = ashiftrt64 (riscv_cpu->regs[rs1], shamt_imm);
343 store_rd (cpu, rd, tmp);
344 break;
345 case MATCH_SRAIW:
346 TRACE_INSN (cpu, "sraiw %s, %s, %" PRIiTW "; // %s = %s >>> %#" PRIxTW,
347 rd_name, rs1_name, shamt_imm, rd_name, rs1_name, shamt_imm);
348 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
349 store_rd (cpu, rd, EXTEND32 (
350 ashiftrt ((int32_t) riscv_cpu->regs[rs1], shamt_imm)));
351 break;
352 case MATCH_SLT:
353 TRACE_INSN (cpu, "slt");
354 store_rd (cpu, rd,
355 !!((signed_word) riscv_cpu->regs[rs1] <
356 (signed_word) riscv_cpu->regs[rs2]));
357 break;
358 case MATCH_SLTU:
359 TRACE_INSN (cpu, "sltu");
360 store_rd (cpu, rd, !!((unsigned_word) riscv_cpu->regs[rs1] <
361 (unsigned_word) riscv_cpu->regs[rs2]));
362 break;
363 case MATCH_SLTI:
364 TRACE_INSN (cpu, "slti");
365 store_rd (cpu, rd, !!((signed_word) riscv_cpu->regs[rs1] <
366 (signed_word) i_imm));
367 break;
368 case MATCH_SLTIU:
369 TRACE_INSN (cpu, "sltiu");
370 store_rd (cpu, rd, !!((unsigned_word) riscv_cpu->regs[rs1] <
371 (unsigned_word) i_imm));
372 break;
373 case MATCH_AUIPC:
374 TRACE_INSN (cpu, "auipc %s, %" PRIiTW "; // %s = pc + %" PRIiTW,
375 rd_name, u_imm, rd_name, u_imm);
376 store_rd (cpu, rd, riscv_cpu->pc + u_imm);
377 break;
378 case MATCH_BEQ:
379 TRACE_INSN (cpu, "beq %s, %s, %#" PRIxTW "; "
380 "// if (%s == %s) goto %#" PRIxTW,
381 rs1_name, rs2_name, sb_imm, rs1_name, rs2_name, sb_imm);
382 if (riscv_cpu->regs[rs1] == riscv_cpu->regs[rs2])
384 pc = riscv_cpu->pc + sb_imm;
385 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
387 break;
388 case MATCH_BLT:
389 TRACE_INSN (cpu, "blt %s, %s, %#" PRIxTW "; "
390 "// if (%s < %s) goto %#" PRIxTW,
391 rs1_name, rs2_name, sb_imm, rs1_name, rs2_name, sb_imm);
392 if ((signed_word) riscv_cpu->regs[rs1] <
393 (signed_word) riscv_cpu->regs[rs2])
395 pc = riscv_cpu->pc + sb_imm;
396 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
398 break;
399 case MATCH_BLTU:
400 TRACE_INSN (cpu, "bltu %s, %s, %#" PRIxTW "; "
401 "// if (%s < %s) goto %#" PRIxTW,
402 rs1_name, rs2_name, sb_imm, rs1_name, rs2_name, sb_imm);
403 if ((unsigned_word) riscv_cpu->regs[rs1] <
404 (unsigned_word) riscv_cpu->regs[rs2])
406 pc = riscv_cpu->pc + sb_imm;
407 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
409 break;
410 case MATCH_BGE:
411 TRACE_INSN (cpu, "bge %s, %s, %#" PRIxTW "; "
412 "// if (%s >= %s) goto %#" PRIxTW,
413 rs1_name, rs2_name, sb_imm, rs1_name, rs2_name, sb_imm);
414 if ((signed_word) riscv_cpu->regs[rs1] >=
415 (signed_word) riscv_cpu->regs[rs2])
417 pc = riscv_cpu->pc + sb_imm;
418 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
420 break;
421 case MATCH_BGEU:
422 TRACE_INSN (cpu, "bgeu %s, %s, %#" PRIxTW "; "
423 "// if (%s >= %s) goto %#" PRIxTW,
424 rs1_name, rs2_name, sb_imm, rs1_name, rs2_name, sb_imm);
425 if ((unsigned_word) riscv_cpu->regs[rs1] >=
426 (unsigned_word) riscv_cpu->regs[rs2])
428 pc = riscv_cpu->pc + sb_imm;
429 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
431 break;
432 case MATCH_BNE:
433 TRACE_INSN (cpu, "bne %s, %s, %#" PRIxTW "; "
434 "// if (%s != %s) goto %#" PRIxTW,
435 rs1_name, rs2_name, sb_imm, rs1_name, rs2_name, sb_imm);
436 if (riscv_cpu->regs[rs1] != riscv_cpu->regs[rs2])
438 pc = riscv_cpu->pc + sb_imm;
439 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
441 break;
442 case MATCH_JAL:
443 TRACE_INSN (cpu, "jal %s, %" PRIiTW ";", rd_name,
444 EXTRACT_JTYPE_IMM (iw));
445 store_rd (cpu, rd, riscv_cpu->pc + 4);
446 pc = riscv_cpu->pc + EXTRACT_JTYPE_IMM (iw);
447 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
448 break;
449 case MATCH_JALR:
450 TRACE_INSN (cpu, "jalr %s, %s, %" PRIiTW ";", rd_name, rs1_name, i_imm);
451 pc = riscv_cpu->regs[rs1] + i_imm;
452 store_rd (cpu, rd, riscv_cpu->pc + 4);
453 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
454 break;
456 case MATCH_LD:
457 TRACE_INSN (cpu, "ld %s, %" PRIiTW "(%s);",
458 rd_name, i_imm, rs1_name);
459 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
460 store_rd (cpu, rd,
461 sim_core_read_unaligned_8 (cpu, riscv_cpu->pc, read_map,
462 riscv_cpu->regs[rs1] + i_imm));
463 break;
464 case MATCH_LW:
465 TRACE_INSN (cpu, "lw %s, %" PRIiTW "(%s);",
466 rd_name, i_imm, rs1_name);
467 store_rd (cpu, rd, EXTEND32 (
468 sim_core_read_unaligned_4 (cpu, riscv_cpu->pc, read_map,
469 riscv_cpu->regs[rs1] + i_imm)));
470 break;
471 case MATCH_LWU:
472 TRACE_INSN (cpu, "lwu %s, %" PRIiTW "(%s);",
473 rd_name, i_imm, rs1_name);
474 store_rd (cpu, rd,
475 sim_core_read_unaligned_4 (cpu, riscv_cpu->pc, read_map,
476 riscv_cpu->regs[rs1] + i_imm));
477 break;
478 case MATCH_LH:
479 TRACE_INSN (cpu, "lh %s, %" PRIiTW "(%s);",
480 rd_name, i_imm, rs1_name);
481 store_rd (cpu, rd, EXTEND16 (
482 sim_core_read_unaligned_2 (cpu, riscv_cpu->pc, read_map,
483 riscv_cpu->regs[rs1] + i_imm)));
484 break;
485 case MATCH_LHU:
486 TRACE_INSN (cpu, "lbu %s, %" PRIiTW "(%s);",
487 rd_name, i_imm, rs1_name);
488 store_rd (cpu, rd,
489 sim_core_read_unaligned_2 (cpu, riscv_cpu->pc, read_map,
490 riscv_cpu->regs[rs1] + i_imm));
491 break;
492 case MATCH_LB:
493 TRACE_INSN (cpu, "lb %s, %" PRIiTW "(%s);",
494 rd_name, i_imm, rs1_name);
495 store_rd (cpu, rd, EXTEND8 (
496 sim_core_read_unaligned_1 (cpu, riscv_cpu->pc, read_map,
497 riscv_cpu->regs[rs1] + i_imm)));
498 break;
499 case MATCH_LBU:
500 TRACE_INSN (cpu, "lbu %s, %" PRIiTW "(%s);",
501 rd_name, i_imm, rs1_name);
502 store_rd (cpu, rd,
503 sim_core_read_unaligned_1 (cpu, riscv_cpu->pc, read_map,
504 riscv_cpu->regs[rs1] + i_imm));
505 break;
506 case MATCH_SD:
507 TRACE_INSN (cpu, "sd %s, %" PRIiTW "(%s);",
508 rs2_name, s_imm, rs1_name);
509 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
510 sim_core_write_unaligned_8 (cpu, riscv_cpu->pc, write_map,
511 riscv_cpu->regs[rs1] + s_imm,
512 riscv_cpu->regs[rs2]);
513 break;
514 case MATCH_SW:
515 TRACE_INSN (cpu, "sw %s, %" PRIiTW "(%s);",
516 rs2_name, s_imm, rs1_name);
517 sim_core_write_unaligned_4 (cpu, riscv_cpu->pc, write_map,
518 riscv_cpu->regs[rs1] + s_imm,
519 riscv_cpu->regs[rs2]);
520 break;
521 case MATCH_SH:
522 TRACE_INSN (cpu, "sh %s, %" PRIiTW "(%s);",
523 rs2_name, s_imm, rs1_name);
524 sim_core_write_unaligned_2 (cpu, riscv_cpu->pc, write_map,
525 riscv_cpu->regs[rs1] + s_imm,
526 riscv_cpu->regs[rs2]);
527 break;
528 case MATCH_SB:
529 TRACE_INSN (cpu, "sb %s, %" PRIiTW "(%s);",
530 rs2_name, s_imm, rs1_name);
531 sim_core_write_unaligned_1 (cpu, riscv_cpu->pc, write_map,
532 riscv_cpu->regs[rs1] + s_imm,
533 riscv_cpu->regs[rs2]);
534 break;
536 case MATCH_CSRRC:
537 TRACE_INSN (cpu, "csrrc");
538 switch (csr)
540 #define DECLARE_CSR(name, num, ...) \
541 case num: \
542 store_rd (cpu, rd, \
543 fetch_csr (cpu, #name, num, &riscv_cpu->csr.name)); \
544 store_csr (cpu, #name, num, &riscv_cpu->csr.name, \
545 riscv_cpu->csr.name & !riscv_cpu->regs[rs1]); \
546 break;
547 #include "opcode/riscv-opc.h"
548 #undef DECLARE_CSR
550 break;
551 case MATCH_CSRRS:
552 TRACE_INSN (cpu, "csrrs");
553 switch (csr)
555 #define DECLARE_CSR(name, num, ...) \
556 case num: \
557 store_rd (cpu, rd, \
558 fetch_csr (cpu, #name, num, &riscv_cpu->csr.name)); \
559 store_csr (cpu, #name, num, &riscv_cpu->csr.name, \
560 riscv_cpu->csr.name | riscv_cpu->regs[rs1]); \
561 break;
562 #include "opcode/riscv-opc.h"
563 #undef DECLARE_CSR
565 break;
566 case MATCH_CSRRW:
567 TRACE_INSN (cpu, "csrrw");
568 switch (csr)
570 #define DECLARE_CSR(name, num, ...) \
571 case num: \
572 store_rd (cpu, rd, \
573 fetch_csr (cpu, #name, num, &riscv_cpu->csr.name)); \
574 store_csr (cpu, #name, num, &riscv_cpu->csr.name, \
575 riscv_cpu->regs[rs1]); \
576 break;
577 #include "opcode/riscv-opc.h"
578 #undef DECLARE_CSR
580 break;
582 case MATCH_RDCYCLE:
583 TRACE_INSN (cpu, "rdcycle %s;", rd_name);
584 store_rd (cpu, rd,
585 fetch_csr (cpu, "cycle", CSR_CYCLE, &riscv_cpu->csr.cycle));
586 break;
587 case MATCH_RDCYCLEH:
588 TRACE_INSN (cpu, "rdcycleh %s;", rd_name);
589 RISCV_ASSERT_RV32 (cpu, "insn: %s", op->name);
590 store_rd (cpu, rd,
591 fetch_csr (cpu, "cycleh", CSR_CYCLEH, &riscv_cpu->csr.cycleh));
592 break;
593 case MATCH_RDINSTRET:
594 TRACE_INSN (cpu, "rdinstret %s;", rd_name);
595 store_rd (cpu, rd,
596 fetch_csr (cpu, "instret", CSR_INSTRET,
597 &riscv_cpu->csr.instret));
598 break;
599 case MATCH_RDINSTRETH:
600 TRACE_INSN (cpu, "rdinstreth %s;", rd_name);
601 RISCV_ASSERT_RV32 (cpu, "insn: %s", op->name);
602 store_rd (cpu, rd,
603 fetch_csr (cpu, "instreth", CSR_INSTRETH,
604 &riscv_cpu->csr.instreth));
605 break;
606 case MATCH_RDTIME:
607 TRACE_INSN (cpu, "rdtime %s;", rd_name);
608 store_rd (cpu, rd,
609 fetch_csr (cpu, "time", CSR_TIME, &riscv_cpu->csr.time));
610 break;
611 case MATCH_RDTIMEH:
612 TRACE_INSN (cpu, "rdtimeh %s;", rd_name);
613 RISCV_ASSERT_RV32 (cpu, "insn: %s", op->name);
614 store_rd (cpu, rd,
615 fetch_csr (cpu, "timeh", CSR_TIMEH, &riscv_cpu->csr.timeh));
616 break;
618 case MATCH_FENCE:
619 TRACE_INSN (cpu, "fence;");
620 break;
621 case MATCH_FENCE_I:
622 TRACE_INSN (cpu, "fence.i;");
623 break;
624 case MATCH_EBREAK:
625 TRACE_INSN (cpu, "ebreak;");
626 /* GDB expects us to step over EBREAK. */
627 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc + 4, sim_stopped,
628 SIM_SIGTRAP);
629 break;
630 case MATCH_ECALL:
631 TRACE_INSN (cpu, "ecall;");
632 riscv_cpu->a0 = sim_syscall (cpu, riscv_cpu->a7, riscv_cpu->a0,
633 riscv_cpu->a1, riscv_cpu->a2, riscv_cpu->a3);
634 break;
635 default:
636 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
637 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled, SIM_SIGILL);
640 return pc;
643 static uint64_t
644 mulhu (uint64_t a, uint64_t b)
646 #ifdef HAVE___INT128
647 return ((__int128)a * b) >> 64;
648 #else
649 uint64_t t;
650 uint32_t y1, y2, y3;
651 uint64_t a0 = (uint32_t)a, a1 = a >> 32;
652 uint64_t b0 = (uint32_t)b, b1 = b >> 32;
654 t = a1*b0 + ((a0*b0) >> 32);
655 y1 = t;
656 y2 = t >> 32;
658 t = a0*b1 + y1;
659 y1 = t;
661 t = a1*b1 + y2 + (t >> 32);
662 y2 = t;
663 y3 = t >> 32;
665 return ((uint64_t)y3 << 32) | y2;
666 #endif
669 static uint64_t
670 mulh (int64_t a, int64_t b)
672 int negate = (a < 0) != (b < 0);
673 uint64_t res = mulhu (a < 0 ? -a : a, b < 0 ? -b : b);
674 return negate ? ~res + (a * b == 0) : res;
677 static uint64_t
678 mulhsu (int64_t a, uint64_t b)
680 int negate = a < 0;
681 uint64_t res = mulhu (a < 0 ? -a : a, b);
682 return negate ? ~res + (a * b == 0) : res;
685 static sim_cia
686 execute_m (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
688 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
689 SIM_DESC sd = CPU_STATE (cpu);
690 int rd = (iw >> OP_SH_RD) & OP_MASK_RD;
691 int rs1 = (iw >> OP_SH_RS1) & OP_MASK_RS1;
692 int rs2 = (iw >> OP_SH_RS2) & OP_MASK_RS2;
693 const char *rd_name = riscv_gpr_names_abi[rd];
694 const char *rs1_name = riscv_gpr_names_abi[rs1];
695 const char *rs2_name = riscv_gpr_names_abi[rs2];
696 unsigned_word tmp, dividend_max;
697 sim_cia pc = riscv_cpu->pc + 4;
699 dividend_max = -((unsigned_word) 1 << (WITH_TARGET_WORD_BITSIZE - 1));
701 switch (op->match)
703 case MATCH_DIV:
704 TRACE_INSN (cpu, "div %s, %s, %s; // %s = %s / %s",
705 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
706 if (riscv_cpu->regs[rs1] == dividend_max && riscv_cpu->regs[rs2] == -1)
707 tmp = dividend_max;
708 else if (riscv_cpu->regs[rs2])
709 tmp = (signed_word) riscv_cpu->regs[rs1] /
710 (signed_word) riscv_cpu->regs[rs2];
711 else
712 tmp = -1;
713 store_rd (cpu, rd, tmp);
714 break;
715 case MATCH_DIVW:
716 TRACE_INSN (cpu, "divw %s, %s, %s; // %s = %s / %s",
717 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
718 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
719 if (EXTEND32 (riscv_cpu->regs[rs2]) == -1)
720 tmp = 1 << 31;
721 else if (EXTEND32 (riscv_cpu->regs[rs2]))
722 tmp = EXTEND32 (riscv_cpu->regs[rs1]) / EXTEND32 (riscv_cpu->regs[rs2]);
723 else
724 tmp = -1;
725 store_rd (cpu, rd, EXTEND32 (tmp));
726 break;
727 case MATCH_DIVU:
728 TRACE_INSN (cpu, "divu %s, %s, %s; // %s = %s / %s",
729 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
730 if (riscv_cpu->regs[rs2])
731 store_rd (cpu, rd, (unsigned_word) riscv_cpu->regs[rs1]
732 / (unsigned_word) riscv_cpu->regs[rs2]);
733 else
734 store_rd (cpu, rd, -1);
735 break;
736 case MATCH_DIVUW:
737 TRACE_INSN (cpu, "divuw %s, %s, %s; // %s = %s / %s",
738 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
739 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
740 if ((uint32_t) riscv_cpu->regs[rs2])
741 tmp = (uint32_t) riscv_cpu->regs[rs1] / (uint32_t) riscv_cpu->regs[rs2];
742 else
743 tmp = -1;
744 store_rd (cpu, rd, EXTEND32 (tmp));
745 break;
746 case MATCH_MUL:
747 TRACE_INSN (cpu, "mul %s, %s, %s; // %s = %s * %s",
748 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
749 store_rd (cpu, rd, riscv_cpu->regs[rs1] * riscv_cpu->regs[rs2]);
750 break;
751 case MATCH_MULW:
752 TRACE_INSN (cpu, "mulw %s, %s, %s; // %s = %s * %s",
753 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
754 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
755 store_rd (cpu, rd, EXTEND32 ((int32_t) riscv_cpu->regs[rs1]
756 * (int32_t) riscv_cpu->regs[rs2]));
757 break;
758 case MATCH_MULH:
759 TRACE_INSN (cpu, "mulh %s, %s, %s; // %s = %s * %s",
760 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
761 if (RISCV_XLEN (cpu) == 32)
762 store_rd (cpu, rd,
763 ((int64_t)(signed_word) riscv_cpu->regs[rs1]
764 * (int64_t)(signed_word) riscv_cpu->regs[rs2]) >> 32);
765 else
766 store_rd (cpu, rd, mulh (riscv_cpu->regs[rs1], riscv_cpu->regs[rs2]));
767 break;
768 case MATCH_MULHU:
769 TRACE_INSN (cpu, "mulhu %s, %s, %s; // %s = %s * %s",
770 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
771 if (RISCV_XLEN (cpu) == 32)
772 store_rd (cpu, rd, ((uint64_t)riscv_cpu->regs[rs1]
773 * (uint64_t)riscv_cpu->regs[rs2]) >> 32);
774 else
775 store_rd (cpu, rd, mulhu (riscv_cpu->regs[rs1], riscv_cpu->regs[rs2]));
776 break;
777 case MATCH_MULHSU:
778 TRACE_INSN (cpu, "mulhsu %s, %s, %s; // %s = %s * %s",
779 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
780 if (RISCV_XLEN (cpu) == 32)
781 store_rd (cpu, rd, ((int64_t)(signed_word) riscv_cpu->regs[rs1]
782 * (uint64_t)riscv_cpu->regs[rs2]) >> 32);
783 else
784 store_rd (cpu, rd, mulhsu (riscv_cpu->regs[rs1], riscv_cpu->regs[rs2]));
785 break;
786 case MATCH_REM:
787 TRACE_INSN (cpu, "rem %s, %s, %s; // %s = %s %% %s",
788 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
789 if (riscv_cpu->regs[rs1] == dividend_max && riscv_cpu->regs[rs2] == -1)
790 tmp = 0;
791 else if (riscv_cpu->regs[rs2])
792 tmp = (signed_word) riscv_cpu->regs[rs1]
793 % (signed_word) riscv_cpu->regs[rs2];
794 else
795 tmp = riscv_cpu->regs[rs1];
796 store_rd (cpu, rd, tmp);
797 break;
798 case MATCH_REMW:
799 TRACE_INSN (cpu, "remw %s, %s, %s; // %s = %s %% %s",
800 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
801 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
802 if (EXTEND32 (riscv_cpu->regs[rs2]) == -1)
803 tmp = 0;
804 else if (EXTEND32 (riscv_cpu->regs[rs2]))
805 tmp = EXTEND32 (riscv_cpu->regs[rs1]) % EXTEND32 (riscv_cpu->regs[rs2]);
806 else
807 tmp = riscv_cpu->regs[rs1];
808 store_rd (cpu, rd, EXTEND32 (tmp));
809 break;
810 case MATCH_REMU:
811 TRACE_INSN (cpu, "remu %s, %s, %s; // %s = %s %% %s",
812 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
813 if (riscv_cpu->regs[rs2])
814 store_rd (cpu, rd, riscv_cpu->regs[rs1] % riscv_cpu->regs[rs2]);
815 else
816 store_rd (cpu, rd, riscv_cpu->regs[rs1]);
817 break;
818 case MATCH_REMUW:
819 TRACE_INSN (cpu, "remuw %s, %s, %s; // %s = %s %% %s",
820 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
821 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
822 if ((uint32_t) riscv_cpu->regs[rs2])
823 tmp = (uint32_t) riscv_cpu->regs[rs1] % (uint32_t) riscv_cpu->regs[rs2];
824 else
825 tmp = riscv_cpu->regs[rs1];
826 store_rd (cpu, rd, EXTEND32 (tmp));
827 break;
828 default:
829 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
830 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled, SIM_SIGILL);
833 return pc;
836 static sim_cia
837 execute_a (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
839 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
840 SIM_DESC sd = CPU_STATE (cpu);
841 struct riscv_sim_state *state = RISCV_SIM_STATE (sd);
842 int rd = (iw >> OP_SH_RD) & OP_MASK_RD;
843 int rs1 = (iw >> OP_SH_RS1) & OP_MASK_RS1;
844 int rs2 = (iw >> OP_SH_RS2) & OP_MASK_RS2;
845 const char *rd_name = riscv_gpr_names_abi[rd];
846 const char *rs1_name = riscv_gpr_names_abi[rs1];
847 const char *rs2_name = riscv_gpr_names_abi[rs2];
848 struct atomic_mem_reserved_list *amo_prev, *amo_curr;
849 unsigned_word tmp;
850 sim_cia pc = riscv_cpu->pc + 4;
852 /* Handle these two load/store operations specifically. */
853 switch (op->match)
855 case MATCH_LR_W:
856 TRACE_INSN (cpu, "%s %s, (%s);", op->name, rd_name, rs1_name);
857 store_rd (cpu, rd,
858 sim_core_read_unaligned_4 (cpu, riscv_cpu->pc, read_map,
859 riscv_cpu->regs[rs1]));
861 /* Walk the reservation list to find an existing match. */
862 amo_curr = state->amo_reserved_list;
863 while (amo_curr)
865 if (amo_curr->addr == riscv_cpu->regs[rs1])
866 goto done;
867 amo_curr = amo_curr->next;
870 /* No reservation exists, so add one. */
871 amo_curr = xmalloc (sizeof (*amo_curr));
872 amo_curr->addr = riscv_cpu->regs[rs1];
873 amo_curr->next = state->amo_reserved_list;
874 state->amo_reserved_list = amo_curr;
875 goto done;
876 case MATCH_SC_W:
877 TRACE_INSN (cpu, "%s %s, %s, (%s);", op->name, rd_name, rs2_name,
878 rs1_name);
880 /* Walk the reservation list to find a match. */
881 amo_curr = amo_prev = state->amo_reserved_list;
882 while (amo_curr)
884 if (amo_curr->addr == riscv_cpu->regs[rs1])
886 /* We found a reservation, so operate it. */
887 sim_core_write_unaligned_4 (cpu, riscv_cpu->pc, write_map,
888 riscv_cpu->regs[rs1],
889 riscv_cpu->regs[rs2]);
890 store_rd (cpu, rd, 0);
891 if (amo_curr == state->amo_reserved_list)
892 state->amo_reserved_list = amo_curr->next;
893 else
894 amo_prev->next = amo_curr->next;
895 free (amo_curr);
896 goto done;
898 amo_prev = amo_curr;
899 amo_curr = amo_curr->next;
902 /* If we're still here, then no reservation exists, so mark as failed. */
903 store_rd (cpu, rd, 1);
904 goto done;
907 /* Handle the rest of the atomic insns with common code paths. */
908 TRACE_INSN (cpu, "%s %s, %s, (%s);",
909 op->name, rd_name, rs2_name, rs1_name);
910 if (op->xlen_requirement == 64)
911 tmp = sim_core_read_unaligned_8 (cpu, riscv_cpu->pc, read_map,
912 riscv_cpu->regs[rs1]);
913 else
914 tmp = EXTEND32 (sim_core_read_unaligned_4 (cpu, riscv_cpu->pc, read_map,
915 riscv_cpu->regs[rs1]));
916 store_rd (cpu, rd, tmp);
918 switch (op->match)
920 case MATCH_AMOADD_D:
921 case MATCH_AMOADD_W:
922 tmp = riscv_cpu->regs[rd] + riscv_cpu->regs[rs2];
923 break;
924 case MATCH_AMOAND_D:
925 case MATCH_AMOAND_W:
926 tmp = riscv_cpu->regs[rd] & riscv_cpu->regs[rs2];
927 break;
928 case MATCH_AMOMAX_D:
929 case MATCH_AMOMAX_W:
930 tmp = max ((signed_word) riscv_cpu->regs[rd],
931 (signed_word) riscv_cpu->regs[rs2]);
932 break;
933 case MATCH_AMOMAXU_D:
934 case MATCH_AMOMAXU_W:
935 tmp = max ((unsigned_word) riscv_cpu->regs[rd],
936 (unsigned_word) riscv_cpu->regs[rs2]);
937 break;
938 case MATCH_AMOMIN_D:
939 case MATCH_AMOMIN_W:
940 tmp = min ((signed_word) riscv_cpu->regs[rd],
941 (signed_word) riscv_cpu->regs[rs2]);
942 break;
943 case MATCH_AMOMINU_D:
944 case MATCH_AMOMINU_W:
945 tmp = min ((unsigned_word) riscv_cpu->regs[rd],
946 (unsigned_word) riscv_cpu->regs[rs2]);
947 break;
948 case MATCH_AMOOR_D:
949 case MATCH_AMOOR_W:
950 tmp = riscv_cpu->regs[rd] | riscv_cpu->regs[rs2];
951 break;
952 case MATCH_AMOSWAP_D:
953 case MATCH_AMOSWAP_W:
954 tmp = riscv_cpu->regs[rs2];
955 break;
956 case MATCH_AMOXOR_D:
957 case MATCH_AMOXOR_W:
958 tmp = riscv_cpu->regs[rd] ^ riscv_cpu->regs[rs2];
959 break;
960 default:
961 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
962 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled, SIM_SIGILL);
965 if (op->xlen_requirement == 64)
966 sim_core_write_unaligned_8 (cpu, riscv_cpu->pc, write_map,
967 riscv_cpu->regs[rs1], tmp);
968 else
969 sim_core_write_unaligned_4 (cpu, riscv_cpu->pc, write_map,
970 riscv_cpu->regs[rs1], tmp);
972 done:
973 return pc;
976 static sim_cia
977 execute_c (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
979 SIM_DESC sd = CPU_STATE (cpu);
980 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
981 int rd = (iw >> OP_SH_RD) & OP_MASK_RD;
982 int rs1_c = ((iw >> OP_SH_CRS1S) & OP_MASK_CRS1S) + 8;
983 int rs2 = (iw >> OP_SH_CRS2) & OP_MASK_CRS2;
984 int rs2_c = ((iw >> OP_SH_CRS2S) & OP_MASK_CRS2S) + 8;
985 const char *rd_name = riscv_gpr_names_abi[rd];
986 const char *rs1_c_name = riscv_gpr_names_abi[rs1_c];
987 const char *rs2_name = riscv_gpr_names_abi[rs2];
988 const char *rs2_c_name = riscv_gpr_names_abi[rs2_c];
989 signed_word imm;
990 unsigned_word tmp;
991 sim_cia pc = riscv_cpu->pc + 2;
993 switch (op->match)
995 case MATCH_C_JR | MATCH_C_MV:
996 switch (op->mask)
998 case MASK_C_MV:
999 TRACE_INSN (cpu, "c.mv %s, %s; // %s = %s",
1000 rd_name, rs2_name, rd_name, rs2_name);
1001 store_rd (cpu, rd, riscv_cpu->regs[rs2]);
1002 break;
1003 case MASK_C_JR:
1004 TRACE_INSN (cpu, "c.jr %s;",
1005 rd_name);
1006 pc = riscv_cpu->regs[rd];
1007 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
1008 break;
1010 break;
1011 case MATCH_C_J:
1012 imm = EXTRACT_CJTYPE_IMM (iw);
1013 TRACE_INSN (cpu, "c.j %" PRIxTW,
1014 imm);
1015 pc = riscv_cpu->pc + imm;
1016 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
1017 break;
1018 case MATCH_C_JAL | MATCH_C_ADDIW:
1019 /* JAL and ADDIW have the same mask but are only available on RV64 or
1020 RV32 respectively. */
1021 if (RISCV_XLEN (cpu) == 64)
1023 imm = EXTRACT_CJTYPE_IMM (iw);
1024 TRACE_INSN (cpu, "c.jal %" PRIxTW,
1025 imm);
1026 store_rd (cpu, SIM_RISCV_RA_REGNUM, riscv_cpu->pc + 2);
1027 pc = riscv_cpu->pc + imm;
1028 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
1030 else if (RISCV_XLEN (cpu) == 32)
1032 imm = EXTRACT_CITYPE_IMM (iw);
1033 TRACE_INSN (cpu, "c.addiw %s, %s, %#" PRIxTW "; // %s += %#" PRIxTW,
1034 rd_name, rd_name, imm, rd_name, imm);
1035 store_rd (cpu, rd, EXTEND32 (riscv_cpu->regs[rd] + imm));
1037 else
1039 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
1040 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1041 SIM_SIGILL);
1043 break;
1044 case MATCH_C_JALR | MATCH_C_ADD | MATCH_C_EBREAK:
1045 switch (op->mask)
1047 case MASK_C_ADD:
1048 TRACE_INSN (cpu, "c.add %s, %s; // %s += %s",
1049 rd_name, rs2_name, rd_name, rs2_name);
1050 store_rd (cpu, rd, riscv_cpu->regs[rd] + riscv_cpu->regs[rs2]);
1051 break;
1052 case MASK_C_JALR:
1053 TRACE_INSN (cpu, "c.jalr %s, %s;",
1054 riscv_gpr_names_abi[SIM_RISCV_RA_REGNUM], rd_name);
1055 store_rd (cpu, SIM_RISCV_RA_REGNUM, riscv_cpu->pc + 2);
1056 pc = riscv_cpu->regs[rd];
1057 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
1058 break;
1059 case MASK_C_EBREAK:
1060 TRACE_INSN (cpu, "ebreak");
1061 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_stopped,
1062 SIM_SIGTRAP);
1064 break;
1065 case MATCH_C_BEQZ:
1066 imm = EXTRACT_CBTYPE_IMM (iw);
1067 TRACE_INSN (cpu, "c.beqz %s, %#" PRIxTW "; "
1068 "// if (%s == 0) goto %#" PRIxTW,
1069 rs1_c_name, imm, rs1_c_name, riscv_cpu->pc + imm);
1070 if (riscv_cpu->regs[rs1_c] == riscv_cpu->regs[0])
1072 pc = riscv_cpu->pc + imm;
1073 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
1075 break;
1076 case MATCH_C_BNEZ:
1077 imm = EXTRACT_CBTYPE_IMM (iw);
1078 TRACE_INSN (cpu, "c.bnez %s, %#" PRIxTW "; "
1079 "// if (%s != 0) goto %#" PRIxTW,
1080 rs1_c_name, imm, rs1_c_name, riscv_cpu->pc + imm);
1081 if (riscv_cpu->regs[rs1_c] != riscv_cpu->regs[0])
1083 pc = riscv_cpu->pc + imm;
1084 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
1086 break;
1087 case MATCH_C_LWSP:
1088 imm = EXTRACT_CITYPE_LWSP_IMM (iw);
1089 TRACE_INSN (cpu, "c.lwsp %s, %" PRIiTW "(sp);",
1090 rd_name, imm);
1091 store_rd (cpu, rd, EXTEND32 (
1092 sim_core_read_unaligned_4 (cpu, riscv_cpu->pc, read_map,
1093 riscv_cpu->regs[SIM_RISCV_SP_REGNUM]
1094 + imm)));
1095 break;
1096 case MATCH_C_LW:
1097 imm = EXTRACT_CLTYPE_LW_IMM (iw);
1098 TRACE_INSN (cpu, "c.lw %s, %" PRIiTW "(%s);",
1099 rs2_c_name, imm, rs1_c_name);
1100 store_rd (cpu, rs2_c, EXTEND32 (
1101 sim_core_read_unaligned_4 (cpu, riscv_cpu->pc, read_map,
1102 riscv_cpu->regs[rs1_c] + imm)));
1103 break;
1104 case MATCH_C_SWSP:
1105 imm = EXTRACT_CSSTYPE_SWSP_IMM (iw);
1106 TRACE_INSN (cpu, "c.swsp %s, %" PRIiTW "(sp);",
1107 rs2_name, imm);
1108 sim_core_write_unaligned_4 (cpu, riscv_cpu->pc, write_map,
1109 riscv_cpu->regs[SIM_RISCV_SP_REGNUM] + imm,
1110 riscv_cpu->regs[rs2]);
1111 break;
1112 case MATCH_C_SW:
1113 imm = EXTRACT_CLTYPE_LW_IMM (iw);
1114 TRACE_INSN (cpu, "c.sw %s, %" PRIiTW "(%s);",
1115 rs2_c_name, imm, rs1_c_name);
1116 sim_core_write_unaligned_4 (cpu, riscv_cpu->pc, write_map,
1117 riscv_cpu->regs[rs1_c] + (imm),
1118 riscv_cpu->regs[rs2_c]);
1119 break;
1120 case MATCH_C_ADDI:
1121 imm = EXTRACT_CITYPE_IMM (iw);
1122 TRACE_INSN (cpu, "c.addi %s, %s, %#" PRIxTW "; // %s += %#" PRIxTW,
1123 rd_name, rd_name, imm, rd_name, imm);
1124 store_rd (cpu, rd, riscv_cpu->regs[rd] + imm);
1125 break;
1126 case MATCH_C_LUI:
1127 imm = EXTRACT_CITYPE_LUI_IMM (iw);
1128 TRACE_INSN (cpu, "c.lui %s, %#" PRIxTW ";",
1129 rd_name, imm);
1130 store_rd (cpu, rd, imm);
1131 break;
1132 case MATCH_C_LI:
1133 imm = EXTRACT_CITYPE_IMM (iw);
1134 TRACE_INSN (cpu, "c.li %s, %#" PRIxTW "; // %s = %#" PRIxTW,
1135 rd_name, imm, rd_name, imm);
1136 store_rd (cpu, rd, imm);
1137 break;
1138 case MATCH_C_ADDI4SPN:
1139 imm = EXTRACT_CIWTYPE_ADDI4SPN_IMM (iw);
1140 TRACE_INSN (cpu, "c.addi4spn %s, %" PRIiTW "; // %s = sp + %" PRIiTW,
1141 rs2_c_name, imm, rs2_c_name, imm);
1142 store_rd (cpu, rs2_c, riscv_cpu->regs[SIM_RISCV_SP_REGNUM] + (imm));
1143 break;
1144 case MATCH_C_ADDI16SP:
1145 imm = EXTRACT_CITYPE_ADDI16SP_IMM (iw);
1146 TRACE_INSN (cpu, "c.addi16sp %s, %" PRIiTW "; // %s = sp + %" PRIiTW,
1147 rd_name, imm, rd_name, imm);
1148 store_rd (cpu, rd, riscv_cpu->regs[SIM_RISCV_SP_REGNUM] + imm);
1149 break;
1150 case MATCH_C_SUB:
1151 TRACE_INSN (cpu, "c.sub %s, %s; // %s = %s - %s",
1152 rs1_c_name, rs2_c_name, rs1_c_name, rs1_c_name, rs2_c_name);
1153 store_rd (cpu, rs1_c, riscv_cpu->regs[rs1_c] - riscv_cpu->regs[rs2_c]);
1154 break;
1155 case MATCH_C_AND:
1156 TRACE_INSN (cpu, "c.and %s, %s; // %s = %s & %s",
1157 rs1_c_name, rs2_c_name, rs1_c_name, rs1_c_name, rs2_c_name);
1158 store_rd (cpu, rs1_c, riscv_cpu->regs[rs1_c] & riscv_cpu->regs[rs2_c]);
1159 break;
1160 case MATCH_C_OR:
1161 TRACE_INSN (cpu, "c.or %s, %s; // %s = %s | %s",
1162 rs1_c_name, rs2_c_name, rs1_c_name, rs1_c_name, rs2_c_name);
1163 store_rd (cpu, rs1_c, riscv_cpu->regs[rs1_c] | riscv_cpu->regs[rs2_c]);
1164 break;
1165 case MATCH_C_XOR:
1166 TRACE_INSN (cpu, "c.xor %s, %s; // %s = %s ^ %s",
1167 rs1_c_name, rs2_c_name, rs1_c_name, rs1_c_name, rs2_c_name);
1168 store_rd (cpu, rs1_c, riscv_cpu->regs[rs1_c] ^ riscv_cpu->regs[rs2_c]);
1169 break;
1170 case MATCH_C_SLLI | MATCH_C_SLLI64:
1171 if (op->mask == MASK_C_SLLI64)
1173 /* Reserved for custom use. */
1174 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
1175 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1176 SIM_SIGILL);
1177 break;
1179 imm = EXTRACT_CITYPE_IMM (iw);
1180 TRACE_INSN (cpu, "c.slli %s, %" PRIiTW "; // %s = %s << %#" PRIxTW,
1181 rd_name, imm, rd_name, rd_name, imm);
1182 store_rd (cpu, rd, riscv_cpu->regs[rd] << imm);
1183 break;
1184 case MATCH_C_SRLI | MATCH_C_SRLI64:
1185 if (op->mask == MASK_C_SRLI64)
1187 /* Reserved for custom use. */
1188 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
1189 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1190 SIM_SIGILL);
1191 break;
1193 imm = EXTRACT_CITYPE_IMM (iw);
1194 TRACE_INSN (cpu, "c.srli %s, %" PRIiTW "; // %s = %s >> %#" PRIxTW,
1195 rs1_c_name, imm, rs1_c_name, rs1_c_name, imm);
1196 if (RISCV_XLEN (cpu) == 32)
1197 store_rd (cpu, rs1_c,
1198 EXTEND32 ((uint32_t) riscv_cpu->regs[rs1_c] >> imm));
1199 else
1200 store_rd (cpu, rs1_c, riscv_cpu->regs[rs1_c] >> imm);
1201 break;
1202 case MATCH_C_SRAI | MATCH_C_SRAI64:
1203 if (op->mask == MASK_C_SRAI64)
1205 /* Reserved for custom use. */
1206 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
1207 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1208 SIM_SIGILL);
1209 break;
1211 imm = EXTRACT_CITYPE_IMM (iw);
1212 TRACE_INSN (cpu, "c.srai %s, %" PRIiTW "; // %s = %s >> %#" PRIxTW,
1213 rs1_c_name, imm, rs1_c_name, rs1_c_name, imm);
1214 if (RISCV_XLEN (cpu) == 32)
1216 if (imm > 0x1f)
1217 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1218 SIM_SIGILL);
1219 tmp = ashiftrt (riscv_cpu->regs[rs1_c], imm);
1221 else
1222 tmp = ashiftrt64 (riscv_cpu->regs[rs1_c], imm);
1223 store_rd (cpu, rd, tmp);
1224 break;
1225 case MATCH_C_ANDI:
1226 imm = EXTRACT_CITYPE_IMM (iw);
1227 TRACE_INSN (cpu, "c.andi %s, %" PRIiTW "; // %s = %s & %#" PRIxTW,
1228 rs1_c_name, imm, rs1_c_name, rs1_c_name, imm);
1229 store_rd (cpu, rs1_c, riscv_cpu->regs[rs1_c] & imm);
1230 break;
1231 case MATCH_C_ADDW:
1232 TRACE_INSN (cpu, "c.addw %s, %s; // %s = %s + %s",
1233 rs1_c_name, rs2_c_name, rs1_c_name, rs1_c_name, rs2_c_name);
1234 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1235 store_rd (cpu, rs1_c,
1236 EXTEND32 (riscv_cpu->regs[rs1_c] + riscv_cpu->regs[rs2_c]));
1237 break;
1238 case MATCH_C_SUBW:
1239 TRACE_INSN (cpu, "c.subw %s, %s; // %s = %s - %s",
1240 rs1_c_name, rs2_c_name, rs1_c_name, rs1_c_name, rs2_c_name);
1241 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1242 store_rd (cpu, rs1_c,
1243 EXTEND32 (riscv_cpu->regs[rs1_c] - riscv_cpu->regs[rs2_c]));
1244 break;
1245 case MATCH_C_LDSP:
1246 imm = EXTRACT_CITYPE_LDSP_IMM (iw);
1247 TRACE_INSN (cpu, "c.ldsp %s, %" PRIiTW "(sp);",
1248 rd_name, imm);
1249 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1250 store_rd (cpu, rd,
1251 sim_core_read_unaligned_8 (cpu, riscv_cpu->pc, read_map,
1252 riscv_cpu->regs[SIM_RISCV_SP_REGNUM]
1253 + imm));
1254 break;
1255 case MATCH_C_LD:
1256 imm = EXTRACT_CLTYPE_LD_IMM (iw);
1257 TRACE_INSN (cpu, "c.ld %s, %" PRIiTW "(%s);",
1258 rs1_c_name, imm, rs2_c_name);
1259 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1260 store_rd (cpu, rs2_c,
1261 sim_core_read_unaligned_8 (cpu, riscv_cpu->pc, read_map,
1262 riscv_cpu->regs[rs1_c] + imm));
1263 break;
1264 case MATCH_C_SDSP:
1265 imm = EXTRACT_CSSTYPE_SDSP_IMM (iw);
1266 TRACE_INSN (cpu, "c.sdsp %s, %" PRIiTW "(sp);",
1267 rs2_name, imm);
1268 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1269 sim_core_write_unaligned_8 (cpu, riscv_cpu->pc, write_map,
1270 riscv_cpu->regs[SIM_RISCV_SP_REGNUM] + imm,
1271 riscv_cpu->regs[rs2]);
1272 break;
1273 case MATCH_C_SD:
1274 imm = EXTRACT_CLTYPE_LD_IMM (iw);
1275 TRACE_INSN (cpu, "c.sd %s, %" PRIiTW "(%s);",
1276 rs2_c_name, imm, rs1_c_name);
1277 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1278 sim_core_write_unaligned_8 (cpu, riscv_cpu->pc, write_map,
1279 riscv_cpu->regs[rs1_c] + imm,
1280 riscv_cpu->regs[rs2_c]);
1281 break;
1282 default:
1283 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
1284 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1285 SIM_SIGILL);
1288 return pc;
1291 static sim_cia
1292 execute_one (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
1294 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1295 SIM_DESC sd = CPU_STATE (cpu);
1297 if (op->xlen_requirement == 32)
1298 RISCV_ASSERT_RV32 (cpu, "insn: %s", op->name);
1299 else if (op->xlen_requirement == 64)
1300 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1302 switch (op->insn_class)
1304 case INSN_CLASS_A:
1305 return execute_a (cpu, iw, op);
1306 case INSN_CLASS_C:
1307 /* Check whether model with C extension is selected. */
1308 if (riscv_cpu->csr.misa & 4)
1309 return execute_c (cpu, iw, op);
1310 else
1312 TRACE_INSN (cpu, "UNHANDLED EXTENSION: %d", op->insn_class);
1313 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1314 SIM_SIGILL);
1316 case INSN_CLASS_I:
1317 return execute_i (cpu, iw, op);
1318 case INSN_CLASS_M:
1319 case INSN_CLASS_ZMMUL:
1320 return execute_m (cpu, iw, op);
1321 default:
1322 TRACE_INSN (cpu, "UNHANDLED EXTENSION: %d", op->insn_class);
1323 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled, SIM_SIGILL);
1326 return riscv_cpu->pc + riscv_insn_length (iw);
1329 /* Decode & execute a single instruction. */
1330 void step_once (SIM_CPU *cpu)
1332 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1333 SIM_DESC sd = CPU_STATE (cpu);
1334 unsigned_word iw;
1335 unsigned int len;
1336 sim_cia pc = riscv_cpu->pc;
1337 const struct riscv_opcode *op;
1338 int xlen = RISCV_XLEN (cpu);
1340 if (TRACE_ANY_P (cpu))
1341 trace_prefix (sd, cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu),
1342 NULL, 0, " "); /* Use a space for gcc warnings. */
1344 iw = sim_core_read_aligned_2 (cpu, pc, exec_map, pc);
1346 len = riscv_insn_length (iw);
1347 if (len != 4 && len != 2)
1349 sim_io_printf (sd, "sim: bad insn len %#x @ %#" PRIxTA ": %#" PRIxTW "\n",
1350 len, pc, iw);
1351 sim_engine_halt (sd, cpu, NULL, pc, sim_signalled, SIM_SIGILL);
1354 if (len == 4)
1355 iw |= ((unsigned_word) sim_core_read_aligned_2
1356 (cpu, pc, exec_map, pc + 2) << 16);
1358 TRACE_CORE (cpu, "0x%08" PRIxTW, iw);
1360 op = riscv_hash[OP_HASH_IDX (iw)];
1361 if (!op)
1362 sim_engine_halt (sd, cpu, NULL, pc, sim_signalled, SIM_SIGILL);
1364 /* NB: Same loop logic as riscv_disassemble_insn. */
1365 for (; op->name; op++)
1367 /* Does the opcode match? */
1368 if (! op->match_func || ! op->match_func (op, iw))
1369 continue;
1370 /* Is this a pseudo-instruction and may we print it as such? */
1371 if (op->pinfo & INSN_ALIAS)
1372 continue;
1373 /* Is this instruction restricted to a certain value of XLEN? */
1374 if (op->xlen_requirement != 0 && op->xlen_requirement != xlen)
1375 continue;
1377 /* It's a match. */
1378 pc = execute_one (cpu, iw, op);
1379 break;
1382 /* TODO: Handle overflow into high 32 bits. */
1383 /* TODO: Try to use a common counter and only update on demand (reads). */
1384 ++riscv_cpu->csr.cycle;
1385 ++riscv_cpu->csr.instret;
1387 riscv_cpu->pc = pc;
1390 /* Return the program counter for this cpu. */
1391 static sim_cia
1392 pc_get (sim_cpu *cpu)
1394 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1396 return riscv_cpu->pc;
1399 /* Set the program counter for this cpu to the new pc value. */
1400 static void
1401 pc_set (sim_cpu *cpu, sim_cia pc)
1403 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1405 riscv_cpu->pc = pc;
1408 static int
1409 reg_fetch (sim_cpu *cpu, int rn, void *buf, int len)
1411 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1413 if (len <= 0 || len > sizeof (unsigned_word))
1414 return -1;
1416 switch (rn)
1418 case SIM_RISCV_ZERO_REGNUM:
1419 memset (buf, 0, len);
1420 return len;
1421 case SIM_RISCV_RA_REGNUM ... SIM_RISCV_T6_REGNUM:
1422 memcpy (buf, &riscv_cpu->regs[rn], len);
1423 return len;
1424 case SIM_RISCV_FIRST_FP_REGNUM ... SIM_RISCV_LAST_FP_REGNUM:
1425 memcpy (buf, &riscv_cpu->fpregs[rn - SIM_RISCV_FIRST_FP_REGNUM], len);
1426 return len;
1427 case SIM_RISCV_PC_REGNUM:
1428 memcpy (buf, &riscv_cpu->pc, len);
1429 return len;
1431 #define DECLARE_CSR(name, num, ...) \
1432 case SIM_RISCV_ ## num ## _REGNUM: \
1433 memcpy (buf, &riscv_cpu->csr.name, len); \
1434 return len;
1435 #include "opcode/riscv-opc.h"
1436 #undef DECLARE_CSR
1438 default:
1439 return -1;
1443 static int
1444 reg_store (sim_cpu *cpu, int rn, const void *buf, int len)
1446 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1448 if (len <= 0 || len > sizeof (unsigned_word))
1449 return -1;
1451 switch (rn)
1453 case SIM_RISCV_ZERO_REGNUM:
1454 /* Ignore writes. */
1455 return len;
1456 case SIM_RISCV_RA_REGNUM ... SIM_RISCV_T6_REGNUM:
1457 memcpy (&riscv_cpu->regs[rn], buf, len);
1458 return len;
1459 case SIM_RISCV_FIRST_FP_REGNUM ... SIM_RISCV_LAST_FP_REGNUM:
1460 memcpy (&riscv_cpu->fpregs[rn - SIM_RISCV_FIRST_FP_REGNUM], buf, len);
1461 return len;
1462 case SIM_RISCV_PC_REGNUM:
1463 memcpy (&riscv_cpu->pc, buf, len);
1464 return len;
1466 #define DECLARE_CSR(name, num, ...) \
1467 case SIM_RISCV_ ## num ## _REGNUM: \
1468 memcpy (&riscv_cpu->csr.name, buf, len); \
1469 return len;
1470 #include "opcode/riscv-opc.h"
1471 #undef DECLARE_CSR
1473 default:
1474 return -1;
1478 /* Initialize the state for a single cpu. Usuaully this involves clearing all
1479 registers back to their reset state. Should also hook up the fetch/store
1480 helper functions too. */
1481 void
1482 initialize_cpu (SIM_DESC sd, SIM_CPU *cpu, int mhartid)
1484 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1485 const char *extensions;
1486 int i;
1488 memset (riscv_cpu->regs, 0, sizeof (riscv_cpu->regs));
1490 CPU_PC_FETCH (cpu) = pc_get;
1491 CPU_PC_STORE (cpu) = pc_set;
1492 CPU_REG_FETCH (cpu) = reg_fetch;
1493 CPU_REG_STORE (cpu) = reg_store;
1495 if (!riscv_hash[0])
1497 const struct riscv_opcode *op;
1499 for (op = riscv_opcodes; op->name; op++)
1500 if (!riscv_hash[OP_HASH_IDX (op->match)])
1501 riscv_hash[OP_HASH_IDX (op->match)] = op;
1504 riscv_cpu->csr.misa = 0;
1505 /* RV32 sets this field to 0, and we don't really support RV128 yet. */
1506 if (RISCV_XLEN (cpu) == 64)
1507 riscv_cpu->csr.misa |= (uint64_t)2 << 62;
1509 /* Skip the leading "rv" prefix and the two numbers. */
1510 extensions = MODEL_NAME (CPU_MODEL (cpu)) + 4;
1511 for (i = 0; i < 26; ++i)
1513 char ext = 'A' + i;
1515 if (ext == 'X')
1516 continue;
1517 else if (strchr (extensions, ext) != NULL)
1519 if (ext == 'G')
1520 riscv_cpu->csr.misa |= 0x1129; /* G = IMAFD. */
1521 else
1522 riscv_cpu->csr.misa |= (1 << i);
1526 riscv_cpu->csr.mimpid = 0x8000;
1527 riscv_cpu->csr.mhartid = mhartid;
1530 /* Some utils don't like having a NULL environ. */
1531 static const char * const simple_env[] = { "HOME=/", "PATH=/bin", NULL };
1533 /* Count the number of arguments in an argv. */
1534 static int
1535 count_argv (const char * const *argv)
1537 int i;
1539 if (!argv)
1540 return -1;
1542 for (i = 0; argv[i] != NULL; ++i)
1543 continue;
1544 return i;
1547 void
1548 initialize_env (SIM_DESC sd, const char * const *argv, const char * const *env)
1550 SIM_CPU *cpu = STATE_CPU (sd, 0);
1551 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1552 int i;
1553 int argc, argv_flat;
1554 int envc, env_flat;
1555 address_word sp, sp_flat;
1556 unsigned char null[8] = { 0, 0, 0, 0, 0, 0, 0, 0, };
1558 /* Figure out how many bytes the argv strings take up. */
1559 argc = count_argv (argv);
1560 if (argc == -1)
1561 argc = 0;
1562 argv_flat = argc; /* NUL bytes. */
1563 for (i = 0; i < argc; ++i)
1564 argv_flat += strlen (argv[i]);
1566 /* Figure out how many bytes the environ strings take up. */
1567 if (!env)
1568 env = simple_env;
1569 envc = count_argv (env);
1570 env_flat = envc; /* NUL bytes. */
1571 for (i = 0; i < envc; ++i)
1572 env_flat += strlen (env[i]);
1574 /* Make space for the strings themselves. */
1575 sp_flat = (DEFAULT_MEM_SIZE - argv_flat - env_flat) & -sizeof (address_word);
1576 /* Then the pointers to the strings. */
1577 sp = sp_flat - ((argc + 1 + envc + 1) * sizeof (address_word));
1578 /* Then the argc. */
1579 sp -= sizeof (unsigned_word);
1581 /* Set up the regs the libgloss crt0 expects. */
1582 riscv_cpu->a0 = argc;
1583 riscv_cpu->sp = sp;
1585 /* First push the argc value. */
1586 sim_write (sd, sp, &argc, sizeof (unsigned_word));
1587 sp += sizeof (unsigned_word);
1589 /* Then the actual argv strings so we know where to point argv[]. */
1590 for (i = 0; i < argc; ++i)
1592 unsigned len = strlen (argv[i]) + 1;
1593 sim_write (sd, sp_flat, argv[i], len);
1594 sim_write (sd, sp, &sp_flat, sizeof (address_word));
1595 sp_flat += len;
1596 sp += sizeof (address_word);
1598 sim_write (sd, sp, null, sizeof (address_word));
1599 sp += sizeof (address_word);
1601 /* Then the actual env strings so we know where to point env[]. */
1602 for (i = 0; i < envc; ++i)
1604 unsigned len = strlen (env[i]) + 1;
1605 sim_write (sd, sp_flat, env[i], len);
1606 sim_write (sd, sp, &sp_flat, sizeof (address_word));
1607 sp_flat += len;
1608 sp += sizeof (address_word);