1 1.1 christos /* OpenRISC simulator support code 2 1.1.1.4 christos Copyright (C) 2017-2024 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 christos } 210 1.1 christos 211 1.1 christos void 212 1.1 christos or1k32bf_insn_before (sim_cpu *current_cpu, SEM_PC vpc, const IDESC *idesc) 213 1.1 christos { 214 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 215 1.1.1.4 christos struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu); 216 1.1 christos 217 1.1.1.4 christos or1k_cpu->delay_slot = or1k_cpu->next_delay_slot; 218 1.1.1.4 christos or1k_cpu->next_delay_slot = 0; 219 1.1 christos 220 1.1.1.4 christos if (or1k_cpu->delay_slot && 221 1.1 christos CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) & 222 1.1 christos CGEN_ATTR_MASK (CGEN_INSN_NOT_IN_DELAY_SLOT)) 223 1.1 christos { 224 1.1 christos USI pc; 225 1.1 christos #ifdef WITH_SCACHE 226 1.1 christos pc = vpc->argbuf.addr; 227 1.1 christos #else 228 1.1 christos pc = vpc; 229 1.1 christos #endif 230 1.1 christos sim_io_error (sd, "invalid instruction in a delay slot at PC 0x%08x", 231 1.1 christos pc); 232 1.1 christos } 233 1.1 christos 234 1.1 christos } 235 1.1 christos 236 1.1 christos void 237 1.1 christos or1k32bf_insn_after (sim_cpu *current_cpu, SEM_PC vpc, const IDESC *idesc) 238 1.1 christos { 239 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 240 1.1.1.4 christos struct or1k_sim_cpu *or1k_cpu = OR1K_SIM_CPU (current_cpu); 241 1.1 christos USI ppc; 242 1.1 christos 243 1.1 christos #ifdef WITH_SCACHE 244 1.1 christos ppc = vpc->argbuf.addr; 245 1.1 christos #else 246 1.1 christos ppc = vpc; 247 1.1 christos #endif 248 1.1 christos 249 1.1 christos SET_H_SYS_PPC (ppc); 250 1.1 christos 251 1.1 christos if (!GET_H_SYS_CPUCFGR_ND () && 252 1.1 christos CGEN_ATTR_BOOLS (CGEN_INSN_ATTRS ((idesc)->idata)) & 253 1.1 christos CGEN_ATTR_MASK (CGEN_INSN_DELAYED_CTI)) 254 1.1 christos { 255 1.1.1.4 christos SIM_ASSERT (!or1k_cpu->delay_slot); 256 1.1.1.4 christos or1k_cpu->next_delay_slot = 1; 257 1.1 christos } 258 1.1 christos } 259 1.1 christos 260 1.1 christos void 261 1.1 christos or1k32bf_nop (sim_cpu *current_cpu, USI uimm16) 262 1.1 christos { 263 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 264 1.1 christos 265 1.1 christos switch (uimm16) 266 1.1 christos { 267 1.1 christos 268 1.1 christos case NOP_NOP: 269 1.1 christos break; 270 1.1 christos 271 1.1 christos case NOP_EXIT: 272 1.1 christos sim_io_printf (CPU_STATE (current_cpu), "exit(%d)\n", GET_H_GPR (3)); 273 1.1.1.4 christos ATTRIBUTE_FALLTHROUGH; 274 1.1 christos case NOP_EXIT_SILENT: 275 1.1 christos sim_engine_halt (sd, current_cpu, NULL, CPU_PC_GET (current_cpu), 276 1.1 christos sim_exited, GET_H_GPR (3)); 277 1.1 christos break; 278 1.1 christos 279 1.1 christos case NOP_REPORT: 280 1.1 christos sim_io_printf (CPU_STATE (current_cpu), "report(0x%08x);\n", 281 1.1 christos GET_H_GPR (3)); 282 1.1 christos break; 283 1.1 christos 284 1.1 christos case NOP_PUTC: 285 1.1 christos sim_io_printf (CPU_STATE (current_cpu), "%c", 286 1.1 christos (char) (GET_H_GPR (3) & 0xff)); 287 1.1 christos break; 288 1.1 christos 289 1.1 christos default: 290 1.1 christos sim_io_eprintf (sd, "WARNING: l.nop with unsupported code 0x%08x\n", 291 1.1 christos uimm16); 292 1.1 christos break; 293 1.1 christos } 294 1.1 christos 295 1.1 christos } 296 1.1 christos 297 1.1 christos /* Build an address value used for load and store instructions. For example, 298 1.1 christos the instruction 'l.lws rD, I(rA)' will require to load data from the 4 byte 299 1.1 christos address represented by rA + I. Here the argument base is rA, offset is I 300 1.1 christos and the size is the read size in bytes. Note, OpenRISC requires that word 301 1.1 christos and half-word access be word and half-word aligned respectively, the check 302 1.1 christos for alignment is not needed here. */ 303 1.1 christos 304 1.1 christos USI 305 1.1 christos or1k32bf_make_load_store_addr (sim_cpu *current_cpu, USI base, SI offset, 306 1.1 christos int size) 307 1.1 christos { 308 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu); 309 1.1 christos 310 1.1 christos USI addr = base + offset; 311 1.1 christos 312 1.1 christos /* If little endian load/store is enabled we adjust the byte and half-word 313 1.1 christos addresses to the little endian equivalent. */ 314 1.1 christos if (GET_H_SYS_SR_LEE ()) 315 1.1 christos { 316 1.1 christos switch (size) 317 1.1 christos { 318 1.1 christos 319 1.1 christos case 4: /* We are retrieving the entire word no adjustment. */ 320 1.1 christos break; 321 1.1 christos 322 1.1 christos case 2: /* Perform half-word adjustment 0 -> 2, 2 -> 0. */ 323 1.1 christos addr ^= 0x2; 324 1.1 christos break; 325 1.1 christos 326 1.1 christos case 1: /* Perform byte adjustment, 0 -> 3, 2 -> 3, etc. */ 327 1.1 christos addr ^= 0x3; 328 1.1 christos break; 329 1.1 christos 330 1.1 christos default: 331 1.1 christos SIM_ASSERT (0); 332 1.1 christos return 0; 333 1.1 christos } 334 1.1 christos } 335 1.1 christos 336 1.1 christos return addr; 337 1.1 christos } 338 1.1 christos 339 1.1 christos /* The find first 1 instruction returns the location of the first set bit 340 1.1 christos in the argument register. */ 341 1.1 christos 342 1.1 christos USI 343 1.1 christos or1k32bf_ff1 (sim_cpu *current_cpu, USI val) 344 1.1 christos { 345 1.1 christos USI bit; 346 1.1 christos USI ret; 347 1.1 christos for (bit = 1, ret = 1; bit; bit <<= 1, ret++) 348 1.1 christos { 349 1.1 christos if (val & bit) 350 1.1 christos return ret; 351 1.1 christos } 352 1.1 christos return 0; 353 1.1 christos } 354 1.1 christos 355 1.1 christos /* The find last 1 instruction returns the location of the last set bit in 356 1.1 christos the argument register. */ 357 1.1 christos 358 1.1 christos USI 359 1.1 christos or1k32bf_fl1 (sim_cpu *current_cpu, USI val) 360 1.1 christos { 361 1.1 christos USI bit; 362 1.1 christos USI ret; 363 1.1 christos for (bit = 1 << 31, ret = 32; bit; bit >>= 1, ret--) 364 1.1 christos { 365 1.1 christos if (val & bit) 366 1.1 christos return ret; 367 1.1 christos } 368 1.1 christos return 0; 369 1.1 christos } 370