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