1 1.1 christos /* OpenRISC simulator support code 2 1.1.1.5 christos Copyright (C) 2017-2025 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos This file is part of GDB, the GNU debugger. 5 1.1 christos 6 1.1 christos This program is free software; you can redistribute it and/or modify 7 1.1 christos it under the terms of the GNU General Public License as published by 8 1.1 christos the Free Software Foundation; either version 3 of the License, or 9 1.1 christos (at your option) any later version. 10 1.1 christos 11 1.1 christos This program is distributed in the hope that it will be useful, 12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 christos GNU General Public License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU General Public License 17 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 18 1.1 christos 19 1.1.1.3 christos /* This must come before any other includes. */ 20 1.1.1.3 christos #include "defs.h" 21 1.1.1.3 christos 22 1.1 christos #define WANT_CPU_OR1K32BF 23 1.1 christos #define WANT_CPU 24 1.1 christos 25 1.1 christos #include "sim-main.h" 26 1.1 christos #include "symcat.h" 27 1.1 christos #include "cgen-ops.h" 28 1.1 christos #include "cgen-mem.h" 29 1.1 christos #include "cpuall.h" 30 1.1 christos 31 1.1 christos #include <string.h> 32 1.1 christos 33 1.1 christos int 34 1.1.1.3 christos or1k32bf_fetch_register (sim_cpu *current_cpu, int rn, void *buf, int len) 35 1.1 christos { 36 1.1 christos if (rn < 32) 37 1.1 christos SETTWI (buf, GET_H_GPR (rn)); 38 1.1 christos else 39 1.1 christos switch (rn) 40 1.1 christos { 41 1.1 christos case PPC_REGNUM: 42 1.1 christos SETTWI (buf, GET_H_SYS_PPC ()); 43 1.1 christos break; 44 1.1 christos case PC_REGNUM: 45 1.1 christos SETTWI (buf, GET_H_PC ()); 46 1.1 christos break; 47 1.1 christos case SR_REGNUM: 48 1.1 christos SETTWI (buf, GET_H_SYS_SR ()); 49 1.1 christos break; 50 1.1 christos default: 51 1.1 christos return 0; 52 1.1 christos } 53 1.1 christos return sizeof (WI); /* WI from arch.h */ 54 1.1 christos } 55 1.1 christos 56 1.1 christos int 57 1.1.1.3 christos or1k32bf_store_register (sim_cpu *current_cpu, int rn, const void *buf, int len) 58 1.1 christos { 59 1.1 christos if (rn < 32) 60 1.1 christos SET_H_GPR (rn, GETTWI (buf)); 61 1.1 christos else 62 1.1 christos switch (rn) 63 1.1 christos { 64 1.1 christos case PPC_REGNUM: 65 1.1 christos SET_H_SYS_PPC (GETTWI (buf)); 66 1.1 christos break; 67 1.1 christos case PC_REGNUM: 68 1.1 christos SET_H_PC (GETTWI (buf)); 69 1.1 christos break; 70 1.1 christos case SR_REGNUM: 71 1.1 christos SET_H_SYS_SR (GETTWI (buf)); 72 1.1 christos break; 73 1.1 christos default: 74 1.1 christos return 0; 75 1.1 christos } 76 1.1 christos return sizeof (WI); /* WI from arch.h */ 77 1.1 christos } 78 1.1 christos 79 1.1 christos int 80 1.1 christos or1k32bf_model_or1200_u_exec (sim_cpu *current_cpu, const IDESC *idesc, 81 1.1 christos int unit_num, int referenced) 82 1.1 christos { 83 1.1 christos return -1; 84 1.1 christos } 85 1.1 christos 86 1.1 christos int 87 1.1 christos or1k32bf_model_or1200nd_u_exec (sim_cpu *current_cpu, const IDESC *idesc, 88 1.1 christos int unit_num, int referenced) 89 1.1 christos { 90 1.1 christos return -1; 91 1.1 christos } 92 1.1 christos 93 1.1 christos void 94 1.1 christos or1k32bf_model_insn_before (sim_cpu *current_cpu, int first_p) 95 1.1 christos { 96 1.1 christos } 97 1.1 christos 98 1.1 christos void 99 1.1 christos or1k32bf_model_insn_after (sim_cpu *current_cpu, int last_p, int cycles) 100 1.1 christos { 101 1.1 christos } 102 1.1 christos 103 1.1 christos USI 104 1.1 christos or1k32bf_h_spr_get_raw (sim_cpu *current_cpu, USI addr) 105 1.1 christos { 106 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 107 1.1.1.4 christos struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu); 108 1.1.1.4 christos 109 1.1 christos SIM_ASSERT (addr < NUM_SPR); 110 1.1.1.4 christos return or1k_cpu->spr[addr]; 111 1.1 christos } 112 1.1 christos 113 1.1 christos void 114 1.1 christos or1k32bf_h_spr_set_raw (sim_cpu *current_cpu, USI addr, USI val) 115 1.1 christos { 116 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 117 1.1.1.4 christos struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu); 118 1.1.1.4 christos 119 1.1 christos SIM_ASSERT (addr < NUM_SPR); 120 1.1.1.4 christos or1k_cpu->spr[addr] = val; 121 1.1 christos } 122 1.1 christos 123 1.1 christos USI 124 1.1 christos or1k32bf_h_spr_field_get_raw (sim_cpu *current_cpu, USI addr, int msb, int lsb) 125 1.1 christos { 126 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 127 1.1.1.4 christos struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu); 128 1.1.1.4 christos 129 1.1 christos SIM_ASSERT (addr < NUM_SPR); 130 1.1.1.4 christos return LSEXTRACTED (or1k_cpu->spr[addr], msb, lsb); 131 1.1 christos } 132 1.1 christos 133 1.1 christos void 134 1.1 christos or1k32bf_h_spr_field_set_raw (sim_cpu *current_cpu, USI addr, int msb, int lsb, 135 1.1 christos USI val) 136 1.1 christos { 137 1.1.1.4 christos struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu); 138 1.1.1.4 christos 139 1.1.1.4 christos or1k_cpu->spr[addr] &= ~LSMASK32 (msb, lsb); 140 1.1.1.4 christos or1k_cpu->spr[addr] |= LSINSERTED (val, msb, lsb); 141 1.1 christos } 142 1.1 christos 143 1.1 christos /* Initialize a sim cpu object. */ 144 1.1 christos void 145 1.1 christos or1k_cpu_init (SIM_DESC sd, sim_cpu *current_cpu, const USI or1k_vr, 146 1.1 christos const USI or1k_upr, const USI or1k_cpucfgr) 147 1.1 christos { 148 1.1.1.4 christos struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu); 149 1.1.1.4 christos 150 1.1 christos /* Set the configuration registers passed from the user. */ 151 1.1 christos SET_H_SYS_VR (or1k_vr); 152 1.1 christos SET_H_SYS_UPR (or1k_upr); 153 1.1 christos SET_H_SYS_CPUCFGR (or1k_cpucfgr); 154 1.1 christos 155 1.1 christos #define CHECK_SPR_FIELD(GROUP, INDEX, FIELD, test) \ 156 1.1 christos do \ 157 1.1 christos { \ 158 1.1 christos USI field = GET_H_##SYS##_##INDEX##_##FIELD (); \ 159 1.1 christos if (!(test)) \ 160 1.1 christos sim_io_eprintf \ 161 1.1 christos (sd, "WARNING: unsupported %s field in %s register: 0x%x\n", \ 162 1.1 christos #FIELD, #INDEX, field); \ 163 1.1 christos } while (0) 164 1.1 christos 165 1.1 christos /* Set flags indicating if we are in a delay slot or not. */ 166 1.1.1.4 christos or1k_cpu->next_delay_slot = 0; 167 1.1.1.4 christos or1k_cpu->delay_slot = 0; 168 1.1 christos 169 1.1 christos /* Verify any user passed fields and warn on configurations we don't 170 1.1 christos support. */ 171 1.1 christos CHECK_SPR_FIELD (SYS, UPR, UP, field == 1); 172 1.1 christos CHECK_SPR_FIELD (SYS, UPR, DCP, field == 0); 173 1.1 christos CHECK_SPR_FIELD (SYS, UPR, ICP, field == 0); 174 1.1 christos CHECK_SPR_FIELD (SYS, UPR, DMP, field == 0); 175 1.1 christos CHECK_SPR_FIELD (SYS, UPR, MP, field == 0); 176 1.1 christos CHECK_SPR_FIELD (SYS, UPR, IMP, field == 0); 177 1.1 christos CHECK_SPR_FIELD (SYS, UPR, DUP, field == 0); 178 1.1 christos CHECK_SPR_FIELD (SYS, UPR, PCUP, field == 0); 179 1.1 christos CHECK_SPR_FIELD (SYS, UPR, PICP, field == 0); 180 1.1 christos CHECK_SPR_FIELD (SYS, UPR, PMP, field == 0); 181 1.1 christos CHECK_SPR_FIELD (SYS, UPR, TTP, field == 0); 182 1.1 christos CHECK_SPR_FIELD (SYS, UPR, CUP, field == 0); 183 1.1 christos 184 1.1 christos CHECK_SPR_FIELD (SYS, CPUCFGR, NSGR, field == 0); 185 1.1 christos CHECK_SPR_FIELD (SYS, CPUCFGR, CGF, field == 0); 186 1.1 christos CHECK_SPR_FIELD (SYS, CPUCFGR, OB32S, field == 1); 187 1.1 christos CHECK_SPR_FIELD (SYS, CPUCFGR, OF32S, field == 1); 188 1.1 christos CHECK_SPR_FIELD (SYS, CPUCFGR, OB64S, field == 0); 189 1.1 christos CHECK_SPR_FIELD (SYS, CPUCFGR, OF64S, field == 0); 190 1.1 christos CHECK_SPR_FIELD (SYS, CPUCFGR, OV64S, field == 0); 191 1.1 christos 192 1.1 christos #undef CHECK_SPR_FIELD 193 1.1 christos 194 1.1 christos /* Configure the fpu operations and mark fpu available. */ 195 1.1 christos cgen_init_accurate_fpu (current_cpu, CGEN_CPU_FPU (current_cpu), 196 1.1 christos or1k32bf_fpu_error); 197 1.1 christos SET_H_SYS_CPUCFGR_OF32S (1); 198 1.1 christos 199 1.1 christos /* Set the UPR[UP] flag, even if the user tried to unset it, as we always 200 1.1 christos support the Unit Present Register. */ 201 1.1 christos SET_H_SYS_UPR_UP (1); 202 1.1 christos 203 1.1 christos /* Set the supervisor register to indicate we are in supervisor mode and 204 1.1 christos set the Fixed-One bit which must always be set. */ 205 1.1 christos SET_H_SYS_SR (SPR_FIELD_MASK_SYS_SR_SM | SPR_FIELD_MASK_SYS_SR_FO); 206 1.1 christos 207 1.1 christos /* Clear the floating point control status register. */ 208 1.1 christos SET_H_SYS_FPCSR (0); 209 1.1.1.5 christos 210 1.1.1.5 christos /* Set this as the one and only core. */ 211 1.1.1.5 christos SET_H_SYS_NUMCORES (1); 212 1.1.1.5 christos SET_H_SYS_COREID (0); 213 1.1 christos } 214 1.1 christos 215 1.1 christos void 216 1.1 christos or1k32bf_insn_before (sim_cpu *current_cpu, SEM_PC vpc, const IDESC *idesc) 217 1.1 christos { 218 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 219 1.1.1.4 christos struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu); 220 1.1 christos 221 1.1.1.4 christos or1k_cpu->delay_slot = or1k_cpu->next_delay_slot; 222 1.1.1.4 christos or1k_cpu->next_delay_slot = 0; 223 1.1 christos 224 1.1.1.4 christos if (or1k_cpu->delay_slot && 225 1.1 christos CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) & 226 1.1 christos CGEN_ATTR_MASK (CGEN_INSN_NOT_IN_DELAY_SLOT)) 227 1.1 christos { 228 1.1 christos USI pc; 229 1.1 christos #ifdef WITH_SCACHE 230 1.1 christos pc = vpc->argbuf.addr; 231 1.1 christos #else 232 1.1 christos pc = vpc; 233 1.1 christos #endif 234 1.1 christos sim_io_error (sd, "invalid instruction in a delay slot at PC 0x%08x", 235 1.1 christos pc); 236 1.1 christos } 237 1.1 christos 238 1.1 christos } 239 1.1 christos 240 1.1 christos void 241 1.1 christos or1k32bf_insn_after (sim_cpu *current_cpu, SEM_PC vpc, const IDESC *idesc) 242 1.1 christos { 243 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 244 1.1.1.4 christos struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu); 245 1.1 christos USI ppc; 246 1.1 christos 247 1.1 christos #ifdef WITH_SCACHE 248 1.1 christos ppc = vpc->argbuf.addr; 249 1.1 christos #else 250 1.1 christos ppc = vpc; 251 1.1 christos #endif 252 1.1 christos 253 1.1 christos SET_H_SYS_PPC (ppc); 254 1.1 christos 255 1.1 christos if (!GET_H_SYS_CPUCFGR_ND () && 256 1.1 christos CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) & 257 1.1 christos CGEN_ATTR_MASK (CGEN_INSN_DELAYED_CTI)) 258 1.1 christos { 259 1.1.1.4 christos SIM_ASSERT (!or1k_cpu->delay_slot); 260 1.1.1.4 christos or1k_cpu->next_delay_slot = 1; 261 1.1 christos } 262 1.1 christos } 263 1.1 christos 264 1.1 christos void 265 1.1 christos or1k32bf_nop (sim_cpu *current_cpu, USI uimm16) 266 1.1 christos { 267 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 268 1.1 christos 269 1.1 christos switch (uimm16) 270 1.1 christos { 271 1.1 christos 272 1.1 christos case NOP_NOP: 273 1.1 christos break; 274 1.1 christos 275 1.1 christos case NOP_EXIT: 276 1.1 christos sim_io_printf (CPU_STATE (current_cpu), "exit(%d)\n", GET_H_GPR (3)); 277 1.1.1.4 christos ATTRIBUTE_FALLTHROUGH; 278 1.1 christos case NOP_EXIT_SILENT: 279 1.1 christos sim_engine_halt (sd, current_cpu, NULL, CPU_PC_GET (current_cpu), 280 1.1 christos sim_exited, GET_H_GPR (3)); 281 1.1 christos break; 282 1.1 christos 283 1.1 christos case NOP_REPORT: 284 1.1 christos sim_io_printf (CPU_STATE (current_cpu), "report(0x%08x);\n", 285 1.1 christos GET_H_GPR (3)); 286 1.1 christos break; 287 1.1 christos 288 1.1 christos case NOP_PUTC: 289 1.1 christos sim_io_printf (CPU_STATE (current_cpu), "%c", 290 1.1 christos (char) (GET_H_GPR (3) & 0xff)); 291 1.1 christos break; 292 1.1 christos 293 1.1 christos default: 294 1.1 christos sim_io_eprintf (sd, "WARNING: l.nop with unsupported code 0x%08x\n", 295 1.1 christos uimm16); 296 1.1 christos break; 297 1.1 christos } 298 1.1 christos 299 1.1 christos } 300 1.1 christos 301 1.1 christos /* Build an address value used for load and store instructions. For example, 302 1.1 christos the instruction 'l.lws rD, I(rA)' will require to load data from the 4 byte 303 1.1 christos address represented by rA + I. Here the argument base is rA, offset is I 304 1.1 christos and the size is the read size in bytes. Note, OpenRISC requires that word 305 1.1 christos and half-word access be word and half-word aligned respectively, the check 306 1.1 christos for alignment is not needed here. */ 307 1.1 christos 308 1.1 christos USI 309 1.1 christos or1k32bf_make_load_store_addr (sim_cpu *current_cpu, USI base, SI offset, 310 1.1 christos int size) 311 1.1 christos { 312 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 313 1.1 christos 314 1.1 christos USI addr = base + offset; 315 1.1 christos 316 1.1 christos /* If little endian load/store is enabled we adjust the byte and half-word 317 1.1 christos addresses to the little endian equivalent. */ 318 1.1 christos if (GET_H_SYS_SR_LEE ()) 319 1.1 christos { 320 1.1 christos switch (size) 321 1.1 christos { 322 1.1 christos 323 1.1 christos case 4: /* We are retrieving the entire word no adjustment. */ 324 1.1 christos break; 325 1.1 christos 326 1.1 christos case 2: /* Perform half-word adjustment 0 -> 2, 2 -> 0. */ 327 1.1 christos addr ^= 0x2; 328 1.1 christos break; 329 1.1 christos 330 1.1 christos case 1: /* Perform byte adjustment, 0 -> 3, 2 -> 3, etc. */ 331 1.1 christos addr ^= 0x3; 332 1.1 christos break; 333 1.1 christos 334 1.1 christos default: 335 1.1 christos SIM_ASSERT (0); 336 1.1 christos return 0; 337 1.1 christos } 338 1.1 christos } 339 1.1 christos 340 1.1 christos return addr; 341 1.1 christos } 342 1.1 christos 343 1.1 christos /* The find first 1 instruction returns the location of the first set bit 344 1.1 christos in the argument register. */ 345 1.1 christos 346 1.1 christos USI 347 1.1 christos or1k32bf_ff1 (sim_cpu *current_cpu, USI val) 348 1.1 christos { 349 1.1 christos USI bit; 350 1.1 christos USI ret; 351 1.1 christos for (bit = 1, ret = 1; bit; bit <<= 1, ret++) 352 1.1 christos { 353 1.1 christos if (val & bit) 354 1.1 christos return ret; 355 1.1 christos } 356 1.1 christos return 0; 357 1.1 christos } 358 1.1 christos 359 1.1 christos /* The find last 1 instruction returns the location of the last set bit in 360 1.1 christos the argument register. */ 361 1.1 christos 362 1.1 christos USI 363 1.1 christos or1k32bf_fl1 (sim_cpu *current_cpu, USI val) 364 1.1 christos { 365 1.1 christos USI bit; 366 1.1 christos USI ret; 367 1.1 christos for (bit = 1 << 31, ret = 32; bit; bit >>= 1, ret--) 368 1.1 christos { 369 1.1 christos if (val & bit) 370 1.1 christos return ret; 371 1.1 christos } 372 1.1 christos return 0; 373 1.1 christos } 374