Automatic date update in version.in
[binutils-gdb.git] / sim / riscv / sim-main.c
blob378e6f1dc69850e5b1ccbc9d2fc5b0b8f6935385
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 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_stopped, SIM_SIGTRAP);
627 break;
628 case MATCH_ECALL:
629 TRACE_INSN (cpu, "ecall;");
630 riscv_cpu->a0 = sim_syscall (cpu, riscv_cpu->a7, riscv_cpu->a0,
631 riscv_cpu->a1, riscv_cpu->a2, riscv_cpu->a3);
632 break;
633 default:
634 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
635 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled, SIM_SIGILL);
638 return pc;
641 static uint64_t
642 mulhu (uint64_t a, uint64_t b)
644 #ifdef HAVE___INT128
645 return ((__int128)a * b) >> 64;
646 #else
647 uint64_t t;
648 uint32_t y1, y2, y3;
649 uint64_t a0 = (uint32_t)a, a1 = a >> 32;
650 uint64_t b0 = (uint32_t)b, b1 = b >> 32;
652 t = a1*b0 + ((a0*b0) >> 32);
653 y1 = t;
654 y2 = t >> 32;
656 t = a0*b1 + y1;
657 y1 = t;
659 t = a1*b1 + y2 + (t >> 32);
660 y2 = t;
661 y3 = t >> 32;
663 return ((uint64_t)y3 << 32) | y2;
664 #endif
667 static uint64_t
668 mulh (int64_t a, int64_t b)
670 int negate = (a < 0) != (b < 0);
671 uint64_t res = mulhu (a < 0 ? -a : a, b < 0 ? -b : b);
672 return negate ? ~res + (a * b == 0) : res;
675 static uint64_t
676 mulhsu (int64_t a, uint64_t b)
678 int negate = a < 0;
679 uint64_t res = mulhu (a < 0 ? -a : a, b);
680 return negate ? ~res + (a * b == 0) : res;
683 static sim_cia
684 execute_m (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
686 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
687 SIM_DESC sd = CPU_STATE (cpu);
688 int rd = (iw >> OP_SH_RD) & OP_MASK_RD;
689 int rs1 = (iw >> OP_SH_RS1) & OP_MASK_RS1;
690 int rs2 = (iw >> OP_SH_RS2) & OP_MASK_RS2;
691 const char *rd_name = riscv_gpr_names_abi[rd];
692 const char *rs1_name = riscv_gpr_names_abi[rs1];
693 const char *rs2_name = riscv_gpr_names_abi[rs2];
694 unsigned_word tmp, dividend_max;
695 sim_cia pc = riscv_cpu->pc + 4;
697 dividend_max = -((unsigned_word) 1 << (WITH_TARGET_WORD_BITSIZE - 1));
699 switch (op->match)
701 case MATCH_DIV:
702 TRACE_INSN (cpu, "div %s, %s, %s; // %s = %s / %s",
703 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
704 if (riscv_cpu->regs[rs1] == dividend_max && riscv_cpu->regs[rs2] == -1)
705 tmp = dividend_max;
706 else if (riscv_cpu->regs[rs2])
707 tmp = (signed_word) riscv_cpu->regs[rs1] /
708 (signed_word) riscv_cpu->regs[rs2];
709 else
710 tmp = -1;
711 store_rd (cpu, rd, tmp);
712 break;
713 case MATCH_DIVW:
714 TRACE_INSN (cpu, "divw %s, %s, %s; // %s = %s / %s",
715 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
716 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
717 if (EXTEND32 (riscv_cpu->regs[rs2]) == -1)
718 tmp = 1 << 31;
719 else if (EXTEND32 (riscv_cpu->regs[rs2]))
720 tmp = EXTEND32 (riscv_cpu->regs[rs1]) / EXTEND32 (riscv_cpu->regs[rs2]);
721 else
722 tmp = -1;
723 store_rd (cpu, rd, EXTEND32 (tmp));
724 break;
725 case MATCH_DIVU:
726 TRACE_INSN (cpu, "divu %s, %s, %s; // %s = %s / %s",
727 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
728 if (riscv_cpu->regs[rs2])
729 store_rd (cpu, rd, (unsigned_word) riscv_cpu->regs[rs1]
730 / (unsigned_word) riscv_cpu->regs[rs2]);
731 else
732 store_rd (cpu, rd, -1);
733 break;
734 case MATCH_DIVUW:
735 TRACE_INSN (cpu, "divuw %s, %s, %s; // %s = %s / %s",
736 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
737 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
738 if ((uint32_t) riscv_cpu->regs[rs2])
739 tmp = (uint32_t) riscv_cpu->regs[rs1] / (uint32_t) riscv_cpu->regs[rs2];
740 else
741 tmp = -1;
742 store_rd (cpu, rd, EXTEND32 (tmp));
743 break;
744 case MATCH_MUL:
745 TRACE_INSN (cpu, "mul %s, %s, %s; // %s = %s * %s",
746 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
747 store_rd (cpu, rd, riscv_cpu->regs[rs1] * riscv_cpu->regs[rs2]);
748 break;
749 case MATCH_MULW:
750 TRACE_INSN (cpu, "mulw %s, %s, %s; // %s = %s * %s",
751 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
752 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
753 store_rd (cpu, rd, EXTEND32 ((int32_t) riscv_cpu->regs[rs1]
754 * (int32_t) riscv_cpu->regs[rs2]));
755 break;
756 case MATCH_MULH:
757 TRACE_INSN (cpu, "mulh %s, %s, %s; // %s = %s * %s",
758 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
759 if (RISCV_XLEN (cpu) == 32)
760 store_rd (cpu, rd,
761 ((int64_t)(signed_word) riscv_cpu->regs[rs1]
762 * (int64_t)(signed_word) riscv_cpu->regs[rs2]) >> 32);
763 else
764 store_rd (cpu, rd, mulh (riscv_cpu->regs[rs1], riscv_cpu->regs[rs2]));
765 break;
766 case MATCH_MULHU:
767 TRACE_INSN (cpu, "mulhu %s, %s, %s; // %s = %s * %s",
768 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
769 if (RISCV_XLEN (cpu) == 32)
770 store_rd (cpu, rd, ((uint64_t)riscv_cpu->regs[rs1]
771 * (uint64_t)riscv_cpu->regs[rs2]) >> 32);
772 else
773 store_rd (cpu, rd, mulhu (riscv_cpu->regs[rs1], riscv_cpu->regs[rs2]));
774 break;
775 case MATCH_MULHSU:
776 TRACE_INSN (cpu, "mulhsu %s, %s, %s; // %s = %s * %s",
777 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
778 if (RISCV_XLEN (cpu) == 32)
779 store_rd (cpu, rd, ((int64_t)(signed_word) riscv_cpu->regs[rs1]
780 * (uint64_t)riscv_cpu->regs[rs2]) >> 32);
781 else
782 store_rd (cpu, rd, mulhsu (riscv_cpu->regs[rs1], riscv_cpu->regs[rs2]));
783 break;
784 case MATCH_REM:
785 TRACE_INSN (cpu, "rem %s, %s, %s; // %s = %s %% %s",
786 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
787 if (riscv_cpu->regs[rs1] == dividend_max && riscv_cpu->regs[rs2] == -1)
788 tmp = 0;
789 else if (riscv_cpu->regs[rs2])
790 tmp = (signed_word) riscv_cpu->regs[rs1]
791 % (signed_word) riscv_cpu->regs[rs2];
792 else
793 tmp = riscv_cpu->regs[rs1];
794 store_rd (cpu, rd, tmp);
795 break;
796 case MATCH_REMW:
797 TRACE_INSN (cpu, "remw %s, %s, %s; // %s = %s %% %s",
798 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
799 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
800 if (EXTEND32 (riscv_cpu->regs[rs2]) == -1)
801 tmp = 0;
802 else if (EXTEND32 (riscv_cpu->regs[rs2]))
803 tmp = EXTEND32 (riscv_cpu->regs[rs1]) % EXTEND32 (riscv_cpu->regs[rs2]);
804 else
805 tmp = riscv_cpu->regs[rs1];
806 store_rd (cpu, rd, EXTEND32 (tmp));
807 break;
808 case MATCH_REMU:
809 TRACE_INSN (cpu, "remu %s, %s, %s; // %s = %s %% %s",
810 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
811 if (riscv_cpu->regs[rs2])
812 store_rd (cpu, rd, riscv_cpu->regs[rs1] % riscv_cpu->regs[rs2]);
813 else
814 store_rd (cpu, rd, riscv_cpu->regs[rs1]);
815 break;
816 case MATCH_REMUW:
817 TRACE_INSN (cpu, "remuw %s, %s, %s; // %s = %s %% %s",
818 rd_name, rs1_name, rs2_name, rd_name, rs1_name, rs2_name);
819 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
820 if ((uint32_t) riscv_cpu->regs[rs2])
821 tmp = (uint32_t) riscv_cpu->regs[rs1] % (uint32_t) riscv_cpu->regs[rs2];
822 else
823 tmp = riscv_cpu->regs[rs1];
824 store_rd (cpu, rd, EXTEND32 (tmp));
825 break;
826 default:
827 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
828 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled, SIM_SIGILL);
831 return pc;
834 static sim_cia
835 execute_a (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
837 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
838 SIM_DESC sd = CPU_STATE (cpu);
839 struct riscv_sim_state *state = RISCV_SIM_STATE (sd);
840 int rd = (iw >> OP_SH_RD) & OP_MASK_RD;
841 int rs1 = (iw >> OP_SH_RS1) & OP_MASK_RS1;
842 int rs2 = (iw >> OP_SH_RS2) & OP_MASK_RS2;
843 const char *rd_name = riscv_gpr_names_abi[rd];
844 const char *rs1_name = riscv_gpr_names_abi[rs1];
845 const char *rs2_name = riscv_gpr_names_abi[rs2];
846 struct atomic_mem_reserved_list *amo_prev, *amo_curr;
847 unsigned_word tmp;
848 sim_cia pc = riscv_cpu->pc + 4;
850 /* Handle these two load/store operations specifically. */
851 switch (op->match)
853 case MATCH_LR_W:
854 TRACE_INSN (cpu, "%s %s, (%s);", op->name, rd_name, rs1_name);
855 store_rd (cpu, rd,
856 sim_core_read_unaligned_4 (cpu, riscv_cpu->pc, read_map,
857 riscv_cpu->regs[rs1]));
859 /* Walk the reservation list to find an existing match. */
860 amo_curr = state->amo_reserved_list;
861 while (amo_curr)
863 if (amo_curr->addr == riscv_cpu->regs[rs1])
864 goto done;
865 amo_curr = amo_curr->next;
868 /* No reservation exists, so add one. */
869 amo_curr = xmalloc (sizeof (*amo_curr));
870 amo_curr->addr = riscv_cpu->regs[rs1];
871 amo_curr->next = state->amo_reserved_list;
872 state->amo_reserved_list = amo_curr;
873 goto done;
874 case MATCH_SC_W:
875 TRACE_INSN (cpu, "%s %s, %s, (%s);", op->name, rd_name, rs2_name,
876 rs1_name);
878 /* Walk the reservation list to find a match. */
879 amo_curr = amo_prev = state->amo_reserved_list;
880 while (amo_curr)
882 if (amo_curr->addr == riscv_cpu->regs[rs1])
884 /* We found a reservation, so operate it. */
885 sim_core_write_unaligned_4 (cpu, riscv_cpu->pc, write_map,
886 riscv_cpu->regs[rs1],
887 riscv_cpu->regs[rs2]);
888 store_rd (cpu, rd, 0);
889 if (amo_curr == state->amo_reserved_list)
890 state->amo_reserved_list = amo_curr->next;
891 else
892 amo_prev->next = amo_curr->next;
893 free (amo_curr);
894 goto done;
896 amo_prev = amo_curr;
897 amo_curr = amo_curr->next;
900 /* If we're still here, then no reservation exists, so mark as failed. */
901 store_rd (cpu, rd, 1);
902 goto done;
905 /* Handle the rest of the atomic insns with common code paths. */
906 TRACE_INSN (cpu, "%s %s, %s, (%s);",
907 op->name, rd_name, rs2_name, rs1_name);
908 if (op->xlen_requirement == 64)
909 tmp = sim_core_read_unaligned_8 (cpu, riscv_cpu->pc, read_map,
910 riscv_cpu->regs[rs1]);
911 else
912 tmp = EXTEND32 (sim_core_read_unaligned_4 (cpu, riscv_cpu->pc, read_map,
913 riscv_cpu->regs[rs1]));
914 store_rd (cpu, rd, tmp);
916 switch (op->match)
918 case MATCH_AMOADD_D:
919 case MATCH_AMOADD_W:
920 tmp = riscv_cpu->regs[rd] + riscv_cpu->regs[rs2];
921 break;
922 case MATCH_AMOAND_D:
923 case MATCH_AMOAND_W:
924 tmp = riscv_cpu->regs[rd] & riscv_cpu->regs[rs2];
925 break;
926 case MATCH_AMOMAX_D:
927 case MATCH_AMOMAX_W:
928 tmp = max ((signed_word) riscv_cpu->regs[rd],
929 (signed_word) riscv_cpu->regs[rs2]);
930 break;
931 case MATCH_AMOMAXU_D:
932 case MATCH_AMOMAXU_W:
933 tmp = max ((unsigned_word) riscv_cpu->regs[rd],
934 (unsigned_word) riscv_cpu->regs[rs2]);
935 break;
936 case MATCH_AMOMIN_D:
937 case MATCH_AMOMIN_W:
938 tmp = min ((signed_word) riscv_cpu->regs[rd],
939 (signed_word) riscv_cpu->regs[rs2]);
940 break;
941 case MATCH_AMOMINU_D:
942 case MATCH_AMOMINU_W:
943 tmp = min ((unsigned_word) riscv_cpu->regs[rd],
944 (unsigned_word) riscv_cpu->regs[rs2]);
945 break;
946 case MATCH_AMOOR_D:
947 case MATCH_AMOOR_W:
948 tmp = riscv_cpu->regs[rd] | riscv_cpu->regs[rs2];
949 break;
950 case MATCH_AMOSWAP_D:
951 case MATCH_AMOSWAP_W:
952 tmp = riscv_cpu->regs[rs2];
953 break;
954 case MATCH_AMOXOR_D:
955 case MATCH_AMOXOR_W:
956 tmp = riscv_cpu->regs[rd] ^ riscv_cpu->regs[rs2];
957 break;
958 default:
959 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
960 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled, SIM_SIGILL);
963 if (op->xlen_requirement == 64)
964 sim_core_write_unaligned_8 (cpu, riscv_cpu->pc, write_map,
965 riscv_cpu->regs[rs1], tmp);
966 else
967 sim_core_write_unaligned_4 (cpu, riscv_cpu->pc, write_map,
968 riscv_cpu->regs[rs1], tmp);
970 done:
971 return pc;
974 static sim_cia
975 execute_c (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
977 SIM_DESC sd = CPU_STATE (cpu);
978 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
979 int rd = (iw >> OP_SH_RD) & OP_MASK_RD;
980 int rs1_c = ((iw >> OP_SH_CRS1S) & OP_MASK_CRS1S) + 8;
981 int rs2 = (iw >> OP_SH_CRS2) & OP_MASK_CRS2;
982 int rs2_c = ((iw >> OP_SH_CRS2S) & OP_MASK_CRS2S) + 8;
983 const char *rd_name = riscv_gpr_names_abi[rd];
984 const char *rs1_c_name = riscv_gpr_names_abi[rs1_c];
985 const char *rs2_name = riscv_gpr_names_abi[rs2];
986 const char *rs2_c_name = riscv_gpr_names_abi[rs2_c];
987 signed_word imm;
988 unsigned_word tmp;
989 sim_cia pc = riscv_cpu->pc + 2;
991 switch (op->match)
993 case MATCH_C_JR | MATCH_C_MV:
994 switch (op->mask)
996 case MASK_C_MV:
997 TRACE_INSN (cpu, "c.mv %s, %s; // %s = %s",
998 rd_name, rs2_name, rd_name, rs2_name);
999 store_rd (cpu, rd, riscv_cpu->regs[rs2]);
1000 break;
1001 case MASK_C_JR:
1002 TRACE_INSN (cpu, "c.jr %s;",
1003 rd_name);
1004 pc = riscv_cpu->regs[rd];
1005 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
1006 break;
1008 break;
1009 case MATCH_C_J:
1010 imm = EXTRACT_CJTYPE_IMM (iw);
1011 TRACE_INSN (cpu, "c.j %" PRIxTW,
1012 imm);
1013 pc = riscv_cpu->pc + imm;
1014 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
1015 break;
1016 case MATCH_C_JAL | MATCH_C_ADDIW:
1017 /* JAL and ADDIW have the same mask but are only available on RV32 or
1018 RV64 respectively. */
1019 if (RISCV_XLEN (cpu) == 32)
1021 imm = EXTRACT_CJTYPE_IMM (iw);
1022 TRACE_INSN (cpu, "c.jal %" PRIxTW,
1023 imm);
1024 store_rd (cpu, SIM_RISCV_RA_REGNUM, riscv_cpu->pc + 2);
1025 pc = riscv_cpu->pc + imm;
1026 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
1028 else if (RISCV_XLEN (cpu) == 64)
1030 imm = EXTRACT_CITYPE_IMM (iw);
1031 TRACE_INSN (cpu, "c.addiw %s, %s, %#" PRIxTW "; // %s += %#" PRIxTW,
1032 rd_name, rd_name, imm, rd_name, imm);
1033 store_rd (cpu, rd, EXTEND32 (riscv_cpu->regs[rd] + imm));
1035 else
1037 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
1038 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1039 SIM_SIGILL);
1041 break;
1042 case MATCH_C_JALR | MATCH_C_ADD | MATCH_C_EBREAK:
1043 switch (op->mask)
1045 case MASK_C_ADD:
1046 TRACE_INSN (cpu, "c.add %s, %s; // %s += %s",
1047 rd_name, rs2_name, rd_name, rs2_name);
1048 store_rd (cpu, rd, riscv_cpu->regs[rd] + riscv_cpu->regs[rs2]);
1049 break;
1050 case MASK_C_JALR:
1051 TRACE_INSN (cpu, "c.jalr %s, %s;",
1052 riscv_gpr_names_abi[SIM_RISCV_RA_REGNUM], rd_name);
1053 store_rd (cpu, SIM_RISCV_RA_REGNUM, riscv_cpu->pc + 2);
1054 pc = riscv_cpu->regs[rd];
1055 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
1056 break;
1057 case MASK_C_EBREAK:
1058 TRACE_INSN (cpu, "ebreak");
1059 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_stopped,
1060 SIM_SIGTRAP);
1062 break;
1063 case MATCH_C_BEQZ:
1064 imm = EXTRACT_CBTYPE_IMM (iw);
1065 TRACE_INSN (cpu, "c.beqz %s, %#" PRIxTW "; "
1066 "// if (%s == 0) goto %#" PRIxTW,
1067 rs1_c_name, imm, rs1_c_name, riscv_cpu->pc + imm);
1068 if (riscv_cpu->regs[rs1_c] == riscv_cpu->regs[0])
1070 pc = riscv_cpu->pc + imm;
1071 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
1073 break;
1074 case MATCH_C_BNEZ:
1075 imm = EXTRACT_CBTYPE_IMM (iw);
1076 TRACE_INSN (cpu, "c.bnez %s, %#" PRIxTW "; "
1077 "// if (%s != 0) goto %#" PRIxTW,
1078 rs1_c_name, imm, rs1_c_name, riscv_cpu->pc + imm);
1079 if (riscv_cpu->regs[rs1_c] != riscv_cpu->regs[0])
1081 pc = riscv_cpu->pc + imm;
1082 TRACE_BRANCH (cpu, "to %#" PRIxTW, pc);
1084 break;
1085 case MATCH_C_LWSP:
1086 imm = EXTRACT_CITYPE_LWSP_IMM (iw);
1087 TRACE_INSN (cpu, "c.lwsp %s, %" PRIiTW "(sp);",
1088 rd_name, imm);
1089 store_rd (cpu, rd, EXTEND32 (
1090 sim_core_read_unaligned_4 (cpu, riscv_cpu->pc, read_map,
1091 riscv_cpu->regs[SIM_RISCV_SP_REGNUM]
1092 + imm)));
1093 break;
1094 case MATCH_C_LW:
1095 imm = EXTRACT_CLTYPE_LW_IMM (iw);
1096 TRACE_INSN (cpu, "c.lw %s, %" PRIiTW "(%s);",
1097 rs2_c_name, imm, rs1_c_name);
1098 store_rd (cpu, rs2_c, EXTEND32 (
1099 sim_core_read_unaligned_4 (cpu, riscv_cpu->pc, read_map,
1100 riscv_cpu->regs[rs1_c] + imm)));
1101 break;
1102 case MATCH_C_SWSP:
1103 imm = EXTRACT_CSSTYPE_SWSP_IMM (iw);
1104 TRACE_INSN (cpu, "c.swsp %s, %" PRIiTW "(sp);",
1105 rs2_name, imm);
1106 sim_core_write_unaligned_4 (cpu, riscv_cpu->pc, write_map,
1107 riscv_cpu->regs[SIM_RISCV_SP_REGNUM] + imm,
1108 riscv_cpu->regs[rs2]);
1109 break;
1110 case MATCH_C_SW:
1111 imm = EXTRACT_CLTYPE_LW_IMM (iw);
1112 TRACE_INSN (cpu, "c.sw %s, %" PRIiTW "(%s);",
1113 rs2_c_name, imm, rs1_c_name);
1114 sim_core_write_unaligned_4 (cpu, riscv_cpu->pc, write_map,
1115 riscv_cpu->regs[rs1_c] + (imm),
1116 riscv_cpu->regs[rs2_c]);
1117 break;
1118 case MATCH_C_ADDI:
1119 imm = EXTRACT_CITYPE_IMM (iw);
1120 TRACE_INSN (cpu, "c.addi %s, %s, %#" PRIxTW "; // %s += %#" PRIxTW,
1121 rd_name, rd_name, imm, rd_name, imm);
1122 store_rd (cpu, rd, riscv_cpu->regs[rd] + imm);
1123 break;
1124 case MATCH_C_LUI:
1125 imm = EXTRACT_CITYPE_LUI_IMM (iw);
1126 TRACE_INSN (cpu, "c.lui %s, %#" PRIxTW ";",
1127 rd_name, imm);
1128 store_rd (cpu, rd, imm);
1129 break;
1130 case MATCH_C_LI:
1131 imm = EXTRACT_CITYPE_IMM (iw);
1132 TRACE_INSN (cpu, "c.li %s, %#" PRIxTW "; // %s = %#" PRIxTW,
1133 rd_name, imm, rd_name, imm);
1134 store_rd (cpu, rd, imm);
1135 break;
1136 case MATCH_C_ADDI4SPN:
1137 imm = EXTRACT_CIWTYPE_ADDI4SPN_IMM (iw);
1138 TRACE_INSN (cpu, "c.addi4spn %s, %" PRIiTW "; // %s = sp + %" PRIiTW,
1139 rs2_c_name, imm, rs2_c_name, imm);
1140 store_rd (cpu, rs2_c, riscv_cpu->regs[SIM_RISCV_SP_REGNUM] + (imm));
1141 break;
1142 case MATCH_C_ADDI16SP:
1143 imm = EXTRACT_CITYPE_ADDI16SP_IMM (iw);
1144 TRACE_INSN (cpu, "c.addi16sp %s, %" PRIiTW "; // %s = sp + %" PRIiTW,
1145 rd_name, imm, rd_name, imm);
1146 store_rd (cpu, rd, riscv_cpu->regs[SIM_RISCV_SP_REGNUM] + imm);
1147 break;
1148 case MATCH_C_SUB:
1149 TRACE_INSN (cpu, "c.sub %s, %s; // %s = %s - %s",
1150 rs1_c_name, rs2_c_name, rs1_c_name, rs1_c_name, rs2_c_name);
1151 store_rd (cpu, rs1_c, riscv_cpu->regs[rs1_c] - riscv_cpu->regs[rs2_c]);
1152 break;
1153 case MATCH_C_AND:
1154 TRACE_INSN (cpu, "c.and %s, %s; // %s = %s & %s",
1155 rs1_c_name, rs2_c_name, rs1_c_name, rs1_c_name, rs2_c_name);
1156 store_rd (cpu, rs1_c, riscv_cpu->regs[rs1_c] & riscv_cpu->regs[rs2_c]);
1157 break;
1158 case MATCH_C_OR:
1159 TRACE_INSN (cpu, "c.or %s, %s; // %s = %s | %s",
1160 rs1_c_name, rs2_c_name, rs1_c_name, rs1_c_name, rs2_c_name);
1161 store_rd (cpu, rs1_c, riscv_cpu->regs[rs1_c] | riscv_cpu->regs[rs2_c]);
1162 break;
1163 case MATCH_C_XOR:
1164 TRACE_INSN (cpu, "c.xor %s, %s; // %s = %s ^ %s",
1165 rs1_c_name, rs2_c_name, rs1_c_name, rs1_c_name, rs2_c_name);
1166 store_rd (cpu, rs1_c, riscv_cpu->regs[rs1_c] ^ riscv_cpu->regs[rs2_c]);
1167 break;
1168 case MATCH_C_SLLI | MATCH_C_SLLI64:
1169 if (op->mask == MASK_C_SLLI64)
1171 /* Reserved for custom use. */
1172 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
1173 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1174 SIM_SIGILL);
1175 break;
1177 imm = EXTRACT_CITYPE_IMM (iw);
1178 TRACE_INSN (cpu, "c.slli %s, %" PRIiTW "; // %s = %s << %#" PRIxTW,
1179 rd_name, imm, rd_name, rd_name, imm);
1180 store_rd (cpu, rd, riscv_cpu->regs[rd] << imm);
1181 break;
1182 case MATCH_C_SRLI | MATCH_C_SRLI64:
1183 if (op->mask == MASK_C_SRLI64)
1185 /* Reserved for custom use. */
1186 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
1187 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1188 SIM_SIGILL);
1189 break;
1191 imm = EXTRACT_CITYPE_IMM (iw);
1192 TRACE_INSN (cpu, "c.srli %s, %" PRIiTW "; // %s = %s >> %#" PRIxTW,
1193 rs1_c_name, imm, rs1_c_name, rs1_c_name, imm);
1194 if (RISCV_XLEN (cpu) == 32)
1195 store_rd (cpu, rs1_c,
1196 EXTEND32 ((uint32_t) riscv_cpu->regs[rs1_c] >> imm));
1197 else
1198 store_rd (cpu, rs1_c, riscv_cpu->regs[rs1_c] >> imm);
1199 break;
1200 case MATCH_C_SRAI | MATCH_C_SRAI64:
1201 if (op->mask == MASK_C_SRAI64)
1203 /* Reserved for custom use. */
1204 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
1205 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1206 SIM_SIGILL);
1207 break;
1209 imm = EXTRACT_CITYPE_IMM (iw);
1210 TRACE_INSN (cpu, "c.srai %s, %" PRIiTW "; // %s = %s >> %#" PRIxTW,
1211 rs1_c_name, imm, rs1_c_name, rs1_c_name, imm);
1212 if (RISCV_XLEN (cpu) == 32)
1214 if (imm > 0x1f)
1215 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1216 SIM_SIGILL);
1217 tmp = ashiftrt (riscv_cpu->regs[rs1_c], imm);
1219 else
1220 tmp = ashiftrt64 (riscv_cpu->regs[rs1_c], imm);
1221 store_rd (cpu, rd, tmp);
1222 break;
1223 case MATCH_C_ANDI:
1224 imm = EXTRACT_CITYPE_IMM (iw);
1225 TRACE_INSN (cpu, "c.andi %s, %" PRIiTW "; // %s = %s & %#" PRIxTW,
1226 rs1_c_name, imm, rs1_c_name, rs1_c_name, imm);
1227 store_rd (cpu, rs1_c, riscv_cpu->regs[rs1_c] & imm);
1228 break;
1229 case MATCH_C_ADDW:
1230 TRACE_INSN (cpu, "c.addw %s, %s; // %s = %s + %s",
1231 rs1_c_name, rs2_c_name, rs1_c_name, rs1_c_name, rs2_c_name);
1232 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1233 store_rd (cpu, rs1_c,
1234 EXTEND32 (riscv_cpu->regs[rs1_c] + riscv_cpu->regs[rs2_c]));
1235 break;
1236 case MATCH_C_SUBW:
1237 TRACE_INSN (cpu, "c.subw %s, %s; // %s = %s - %s",
1238 rs1_c_name, rs2_c_name, rs1_c_name, rs1_c_name, rs2_c_name);
1239 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1240 store_rd (cpu, rs1_c,
1241 EXTEND32 (riscv_cpu->regs[rs1_c] - riscv_cpu->regs[rs2_c]));
1242 break;
1243 case MATCH_C_LDSP:
1244 imm = EXTRACT_CITYPE_LDSP_IMM (iw);
1245 TRACE_INSN (cpu, "c.ldsp %s, %" PRIiTW "(sp);",
1246 rd_name, imm);
1247 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1248 store_rd (cpu, rd,
1249 sim_core_read_unaligned_8 (cpu, riscv_cpu->pc, read_map,
1250 riscv_cpu->regs[SIM_RISCV_SP_REGNUM]
1251 + imm));
1252 break;
1253 case MATCH_C_LD:
1254 imm = EXTRACT_CLTYPE_LD_IMM (iw);
1255 TRACE_INSN (cpu, "c.ld %s, %" PRIiTW "(%s);",
1256 rs1_c_name, imm, rs2_c_name);
1257 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1258 store_rd (cpu, rs2_c,
1259 sim_core_read_unaligned_8 (cpu, riscv_cpu->pc, read_map,
1260 riscv_cpu->regs[rs1_c] + imm));
1261 break;
1262 case MATCH_C_SDSP:
1263 imm = EXTRACT_CSSTYPE_SDSP_IMM (iw);
1264 TRACE_INSN (cpu, "c.sdsp %s, %" PRIiTW "(sp);",
1265 rs2_name, imm);
1266 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1267 sim_core_write_unaligned_8 (cpu, riscv_cpu->pc, write_map,
1268 riscv_cpu->regs[SIM_RISCV_SP_REGNUM] + imm,
1269 riscv_cpu->regs[rs2]);
1270 break;
1271 case MATCH_C_SD:
1272 imm = EXTRACT_CLTYPE_LD_IMM (iw);
1273 TRACE_INSN (cpu, "c.sd %s, %" PRIiTW "(%s);",
1274 rs2_c_name, imm, rs1_c_name);
1275 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1276 sim_core_write_unaligned_8 (cpu, riscv_cpu->pc, write_map,
1277 riscv_cpu->regs[rs1_c] + imm,
1278 riscv_cpu->regs[rs2_c]);
1279 break;
1280 default:
1281 TRACE_INSN (cpu, "UNHANDLED INSN: %s", op->name);
1282 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1283 SIM_SIGILL);
1286 return pc;
1289 static sim_cia
1290 execute_one (SIM_CPU *cpu, unsigned_word iw, const struct riscv_opcode *op)
1292 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1293 SIM_DESC sd = CPU_STATE (cpu);
1295 if (op->xlen_requirement == 32)
1296 RISCV_ASSERT_RV32 (cpu, "insn: %s", op->name);
1297 else if (op->xlen_requirement == 64)
1298 RISCV_ASSERT_RV64 (cpu, "insn: %s", op->name);
1300 switch (op->insn_class)
1302 case INSN_CLASS_ZAAMO:
1303 case INSN_CLASS_ZALRSC:
1304 return execute_a (cpu, iw, op);
1305 case INSN_CLASS_C:
1306 /* Check whether model with C extension is selected. */
1307 if (riscv_cpu->csr.misa & 4)
1308 return execute_c (cpu, iw, op);
1309 else
1311 TRACE_INSN (cpu, "UNHANDLED EXTENSION: %d", op->insn_class);
1312 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled,
1313 SIM_SIGILL);
1315 case INSN_CLASS_I:
1316 return execute_i (cpu, iw, op);
1317 case INSN_CLASS_M:
1318 case INSN_CLASS_ZMMUL:
1319 return execute_m (cpu, iw, op);
1320 default:
1321 TRACE_INSN (cpu, "UNHANDLED EXTENSION: %d", op->insn_class);
1322 sim_engine_halt (sd, cpu, NULL, riscv_cpu->pc, sim_signalled, SIM_SIGILL);
1325 return riscv_cpu->pc + riscv_insn_length (iw);
1328 /* Decode & execute a single instruction. */
1329 void step_once (SIM_CPU *cpu)
1331 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1332 SIM_DESC sd = CPU_STATE (cpu);
1333 unsigned_word iw;
1334 unsigned int len;
1335 sim_cia pc = riscv_cpu->pc;
1336 const struct riscv_opcode *op;
1337 int xlen = RISCV_XLEN (cpu);
1339 if (TRACE_ANY_P (cpu))
1340 trace_prefix (sd, cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu),
1341 NULL, 0, " "); /* Use a space for gcc warnings. */
1343 iw = sim_core_read_aligned_2 (cpu, pc, exec_map, pc);
1345 len = riscv_insn_length (iw);
1346 if (len != 4 && len != 2)
1348 sim_io_printf (sd, "sim: bad insn len %#x @ %#" PRIxTA ": %#" PRIxTW "\n",
1349 len, pc, iw);
1350 sim_engine_halt (sd, cpu, NULL, pc, sim_signalled, SIM_SIGILL);
1353 if (len == 4)
1354 iw |= ((unsigned_word) sim_core_read_aligned_2
1355 (cpu, pc, exec_map, pc + 2) << 16);
1357 TRACE_CORE (cpu, "0x%08" PRIxTW, iw);
1359 op = riscv_hash[OP_HASH_IDX (iw)];
1360 if (!op)
1361 sim_engine_halt (sd, cpu, NULL, pc, sim_signalled, SIM_SIGILL);
1363 /* NB: Same loop logic as riscv_disassemble_insn. */
1364 for (; op->name; op++)
1366 /* Does the opcode match? */
1367 if (! op->match_func || ! op->match_func (op, iw))
1368 continue;
1369 /* Is this a pseudo-instruction and may we print it as such? */
1370 if (op->pinfo & INSN_ALIAS)
1371 continue;
1372 /* Is this instruction restricted to a certain value of XLEN? */
1373 if (op->xlen_requirement != 0 && op->xlen_requirement != xlen)
1374 continue;
1376 /* It's a match. */
1377 pc = execute_one (cpu, iw, op);
1378 break;
1381 /* TODO: Handle overflow into high 32 bits. */
1382 /* TODO: Try to use a common counter and only update on demand (reads). */
1383 ++riscv_cpu->csr.cycle;
1384 ++riscv_cpu->csr.instret;
1386 riscv_cpu->pc = pc;
1389 /* Return the program counter for this cpu. */
1390 static sim_cia
1391 pc_get (sim_cpu *cpu)
1393 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1395 return riscv_cpu->pc;
1398 /* Set the program counter for this cpu to the new pc value. */
1399 static void
1400 pc_set (sim_cpu *cpu, sim_cia pc)
1402 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1404 riscv_cpu->pc = pc;
1407 static int
1408 reg_fetch (sim_cpu *cpu, int rn, void *buf, int len)
1410 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1412 if (len <= 0 || len > sizeof (unsigned_word))
1413 return -1;
1415 switch (rn)
1417 case SIM_RISCV_ZERO_REGNUM:
1418 memset (buf, 0, len);
1419 return len;
1420 case SIM_RISCV_RA_REGNUM ... SIM_RISCV_T6_REGNUM:
1421 memcpy (buf, &riscv_cpu->regs[rn], len);
1422 return len;
1423 case SIM_RISCV_FIRST_FP_REGNUM ... SIM_RISCV_LAST_FP_REGNUM:
1424 memcpy (buf, &riscv_cpu->fpregs[rn - SIM_RISCV_FIRST_FP_REGNUM], len);
1425 return len;
1426 case SIM_RISCV_PC_REGNUM:
1427 memcpy (buf, &riscv_cpu->pc, len);
1428 return len;
1430 #define DECLARE_CSR(name, num, ...) \
1431 case SIM_RISCV_ ## num ## _REGNUM: \
1432 memcpy (buf, &riscv_cpu->csr.name, len); \
1433 return len;
1434 #include "opcode/riscv-opc.h"
1435 #undef DECLARE_CSR
1437 default:
1438 return -1;
1442 static int
1443 reg_store (sim_cpu *cpu, int rn, const void *buf, int len)
1445 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1447 if (len <= 0 || len > sizeof (unsigned_word))
1448 return -1;
1450 switch (rn)
1452 case SIM_RISCV_ZERO_REGNUM:
1453 /* Ignore writes. */
1454 return len;
1455 case SIM_RISCV_RA_REGNUM ... SIM_RISCV_T6_REGNUM:
1456 memcpy (&riscv_cpu->regs[rn], buf, len);
1457 return len;
1458 case SIM_RISCV_FIRST_FP_REGNUM ... SIM_RISCV_LAST_FP_REGNUM:
1459 memcpy (&riscv_cpu->fpregs[rn - SIM_RISCV_FIRST_FP_REGNUM], buf, len);
1460 return len;
1461 case SIM_RISCV_PC_REGNUM:
1462 memcpy (&riscv_cpu->pc, buf, len);
1463 return len;
1465 #define DECLARE_CSR(name, num, ...) \
1466 case SIM_RISCV_ ## num ## _REGNUM: \
1467 memcpy (&riscv_cpu->csr.name, buf, len); \
1468 return len;
1469 #include "opcode/riscv-opc.h"
1470 #undef DECLARE_CSR
1472 default:
1473 return -1;
1477 /* Initialize the state for a single cpu. Usuaully this involves clearing all
1478 registers back to their reset state. Should also hook up the fetch/store
1479 helper functions too. */
1480 void
1481 initialize_cpu (SIM_DESC sd, SIM_CPU *cpu, int mhartid)
1483 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1484 const char *extensions;
1485 int i;
1487 memset (riscv_cpu->regs, 0, sizeof (riscv_cpu->regs));
1489 CPU_PC_FETCH (cpu) = pc_get;
1490 CPU_PC_STORE (cpu) = pc_set;
1491 CPU_REG_FETCH (cpu) = reg_fetch;
1492 CPU_REG_STORE (cpu) = reg_store;
1494 if (!riscv_hash[0])
1496 const struct riscv_opcode *op;
1498 for (op = riscv_opcodes; op->name; op++)
1499 if (!riscv_hash[OP_HASH_IDX (op->match)])
1500 riscv_hash[OP_HASH_IDX (op->match)] = op;
1503 riscv_cpu->csr.misa = 0;
1504 /* RV32 sets this field to 0, and we don't really support RV128 yet. */
1505 if (RISCV_XLEN (cpu) == 64)
1506 riscv_cpu->csr.misa |= (uint64_t)2 << 62;
1508 /* Skip the leading "rv" prefix and the two numbers. */
1509 extensions = MODEL_NAME (CPU_MODEL (cpu)) + 4;
1510 for (i = 0; i < 26; ++i)
1512 char ext = 'A' + i;
1514 if (ext == 'X')
1515 continue;
1516 else if (strchr (extensions, ext) != NULL)
1518 if (ext == 'G')
1519 riscv_cpu->csr.misa |= 0x1129; /* G = IMAFD. */
1520 else
1521 riscv_cpu->csr.misa |= (1 << i);
1525 riscv_cpu->csr.mimpid = 0x8000;
1526 riscv_cpu->csr.mhartid = mhartid;
1529 /* Some utils don't like having a NULL environ. */
1530 static const char * const simple_env[] = { "HOME=/", "PATH=/bin", NULL };
1532 /* Count the number of arguments in an argv. */
1533 static int
1534 count_argv (const char * const *argv)
1536 int i;
1538 if (!argv)
1539 return -1;
1541 for (i = 0; argv[i] != NULL; ++i)
1542 continue;
1543 return i;
1546 void
1547 initialize_env (SIM_DESC sd, const char * const *argv, const char * const *env)
1549 SIM_CPU *cpu = STATE_CPU (sd, 0);
1550 struct riscv_sim_cpu *riscv_cpu = RISCV_SIM_CPU (cpu);
1551 int i;
1552 int argc, argv_flat;
1553 int envc, env_flat;
1554 address_word sp, sp_flat;
1555 unsigned char null[8] = { 0, 0, 0, 0, 0, 0, 0, 0, };
1557 /* Figure out how many bytes the argv strings take up. */
1558 argc = count_argv (argv);
1559 if (argc == -1)
1560 argc = 0;
1561 argv_flat = argc; /* NUL bytes. */
1562 for (i = 0; i < argc; ++i)
1563 argv_flat += strlen (argv[i]);
1565 /* Figure out how many bytes the environ strings take up. */
1566 if (!env)
1567 env = simple_env;
1568 envc = count_argv (env);
1569 env_flat = envc; /* NUL bytes. */
1570 for (i = 0; i < envc; ++i)
1571 env_flat += strlen (env[i]);
1573 /* Make space for the strings themselves. */
1574 sp_flat = (DEFAULT_MEM_SIZE - argv_flat - env_flat) & -sizeof (address_word);
1575 /* Then the pointers to the strings. */
1576 sp = sp_flat - ((argc + 1 + envc + 1) * sizeof (address_word));
1577 /* Then the argc. */
1578 sp -= sizeof (unsigned_word);
1579 /* Align to 16 bytes. */
1580 sp = align_down (sp, 16);
1582 /* Set up the regs the libgloss crt0 expects. */
1583 riscv_cpu->a0 = argc;
1584 riscv_cpu->sp = sp;
1586 /* First push the argc value. */
1587 sim_write (sd, sp, &argc, sizeof (unsigned_word));
1588 sp += sizeof (unsigned_word);
1590 /* Then the actual argv strings so we know where to point argv[]. */
1591 for (i = 0; i < argc; ++i)
1593 unsigned len = strlen (argv[i]) + 1;
1594 sim_write (sd, sp_flat, argv[i], len);
1595 sim_write (sd, sp, &sp_flat, sizeof (address_word));
1596 sp_flat += len;
1597 sp += sizeof (address_word);
1599 sim_write (sd, sp, null, sizeof (address_word));
1600 sp += sizeof (address_word);
1602 /* Then the actual env strings so we know where to point env[]. */
1603 for (i = 0; i < envc; ++i)
1605 unsigned len = strlen (env[i]) + 1;
1606 sim_write (sd, sp_flat, env[i], len);
1607 sim_write (sd, sp, &sp_flat, sizeof (address_word));
1608 sp_flat += len;
1609 sp += sizeof (address_word);