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