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