1 1.1 christos /* m32r simulator support code 2 1.11 christos Copyright (C) 1996-2024 Free Software Foundation, Inc. 3 1.1 christos Contributed by Cygnus Support. 4 1.1 christos 5 1.1 christos This file is part of GDB, the GNU debugger. 6 1.1 christos 7 1.1 christos This program is free software; you can redistribute it and/or modify 8 1.1 christos it under the terms of the GNU General Public License as published by 9 1.1 christos the Free Software Foundation; either version 3 of the License, or 10 1.1 christos (at your option) any later version. 11 1.1 christos 12 1.1 christos This program is distributed in the hope that it will be useful, 13 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 christos GNU General Public License for more details. 16 1.1 christos 17 1.1 christos You should have received a copy of the GNU General Public License 18 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 1.1 christos 20 1.10 christos /* This must come before any other includes. */ 21 1.10 christos #include "defs.h" 22 1.10 christos 23 1.1 christos #define WANT_CPU m32rbf 24 1.1 christos #define WANT_CPU_M32RBF 25 1.1 christos 26 1.1 christos #include "sim-main.h" 27 1.1 christos #include "cgen-mem.h" 28 1.1 christos #include "cgen-ops.h" 29 1.10 christos #include <stdlib.h> 30 1.10 christos 31 1.11 christos #include "m32r-sim.h" 32 1.11 christos 33 1.10 christos /* Return the size of REGNO in bytes. */ 34 1.10 christos 35 1.10 christos static int 36 1.10 christos m32rbf_register_size (int regno) 37 1.10 christos { 38 1.10 christos return 4; 39 1.10 christos } 40 1.1 christos 41 1.1 christos /* Decode gdb ctrl register number. */ 42 1.1 christos 43 1.1 christos int 44 1.1 christos m32r_decode_gdb_ctrl_regnum (int gdb_regnum) 45 1.1 christos { 46 1.1 christos switch (gdb_regnum) 47 1.1 christos { 48 1.1 christos case PSW_REGNUM : return H_CR_PSW; 49 1.1 christos case CBR_REGNUM : return H_CR_CBR; 50 1.1 christos case SPI_REGNUM : return H_CR_SPI; 51 1.1 christos case SPU_REGNUM : return H_CR_SPU; 52 1.1 christos case BPC_REGNUM : return H_CR_BPC; 53 1.1 christos case BBPSW_REGNUM : return H_CR_BBPSW; 54 1.1 christos case BBPC_REGNUM : return H_CR_BBPC; 55 1.1 christos case EVB_REGNUM : return H_CR_CR5; 56 1.1 christos } 57 1.1 christos abort (); 58 1.1 christos } 59 1.1 christos 60 1.1 christos /* The contents of BUF are in target byte order. */ 61 1.1 christos 62 1.1 christos int 63 1.10 christos m32rbf_fetch_register (SIM_CPU *current_cpu, int rn, void *buf, int len) 64 1.1 christos { 65 1.10 christos int size = m32rbf_register_size (rn); 66 1.10 christos if (len != size) 67 1.10 christos return -1; 68 1.10 christos 69 1.1 christos if (rn < 16) 70 1.1 christos SETTWI (buf, m32rbf_h_gr_get (current_cpu, rn)); 71 1.1 christos else 72 1.1 christos switch (rn) 73 1.1 christos { 74 1.1 christos case PSW_REGNUM : 75 1.1 christos case CBR_REGNUM : 76 1.1 christos case SPI_REGNUM : 77 1.1 christos case SPU_REGNUM : 78 1.1 christos case BPC_REGNUM : 79 1.1 christos case BBPSW_REGNUM : 80 1.1 christos case BBPC_REGNUM : 81 1.1 christos SETTWI (buf, m32rbf_h_cr_get (current_cpu, 82 1.1 christos m32r_decode_gdb_ctrl_regnum (rn))); 83 1.1 christos break; 84 1.1 christos case PC_REGNUM : 85 1.1 christos SETTWI (buf, m32rbf_h_pc_get (current_cpu)); 86 1.1 christos break; 87 1.1 christos case ACCL_REGNUM : 88 1.1 christos SETTWI (buf, GETLODI (m32rbf_h_accum_get (current_cpu))); 89 1.1 christos break; 90 1.1 christos case ACCH_REGNUM : 91 1.1 christos SETTWI (buf, GETHIDI (m32rbf_h_accum_get (current_cpu))); 92 1.1 christos break; 93 1.1 christos default : 94 1.1 christos return 0; 95 1.1 christos } 96 1.1 christos 97 1.10 christos return size; 98 1.1 christos } 99 1.1 christos 100 1.1 christos /* The contents of BUF are in target byte order. */ 101 1.1 christos 102 1.1 christos int 103 1.10 christos m32rbf_store_register (SIM_CPU *current_cpu, int rn, const void *buf, int len) 104 1.1 christos { 105 1.10 christos int size = m32rbf_register_size (rn); 106 1.10 christos if (len != size) 107 1.10 christos return -1; 108 1.10 christos 109 1.1 christos if (rn < 16) 110 1.1 christos m32rbf_h_gr_set (current_cpu, rn, GETTWI (buf)); 111 1.1 christos else 112 1.1 christos switch (rn) 113 1.1 christos { 114 1.1 christos case PSW_REGNUM : 115 1.1 christos case CBR_REGNUM : 116 1.1 christos case SPI_REGNUM : 117 1.1 christos case SPU_REGNUM : 118 1.1 christos case BPC_REGNUM : 119 1.1 christos case BBPSW_REGNUM : 120 1.1 christos case BBPC_REGNUM : 121 1.1 christos m32rbf_h_cr_set (current_cpu, 122 1.1 christos m32r_decode_gdb_ctrl_regnum (rn), 123 1.1 christos GETTWI (buf)); 124 1.1 christos break; 125 1.1 christos case PC_REGNUM : 126 1.1 christos m32rbf_h_pc_set (current_cpu, GETTWI (buf)); 127 1.1 christos break; 128 1.1 christos case ACCL_REGNUM : 129 1.1 christos { 130 1.1 christos DI val = m32rbf_h_accum_get (current_cpu); 131 1.1 christos SETLODI (val, GETTWI (buf)); 132 1.1 christos m32rbf_h_accum_set (current_cpu, val); 133 1.1 christos break; 134 1.1 christos } 135 1.1 christos case ACCH_REGNUM : 136 1.1 christos { 137 1.1 christos DI val = m32rbf_h_accum_get (current_cpu); 138 1.1 christos SETHIDI (val, GETTWI (buf)); 139 1.1 christos m32rbf_h_accum_set (current_cpu, val); 140 1.1 christos break; 141 1.1 christos } 142 1.1 christos default : 143 1.1 christos return 0; 144 1.1 christos } 145 1.1 christos 146 1.10 christos return size; 147 1.1 christos } 148 1.1 christos 149 1.1 christos USI 151 1.1 christos m32rbf_h_cr_get_handler (SIM_CPU *current_cpu, UINT cr) 152 1.1 christos { 153 1.1 christos switch (cr) 154 1.1 christos { 155 1.1 christos case H_CR_PSW : /* psw */ 156 1.1 christos return (((CPU (h_bpsw) & 0xc1) << 8) 157 1.1 christos | ((CPU (h_psw) & 0xc0) << 0) 158 1.1 christos | GET_H_COND ()); 159 1.1 christos case H_CR_BBPSW : /* backup backup psw */ 160 1.1 christos return CPU (h_bbpsw) & 0xc1; 161 1.1 christos case H_CR_CBR : /* condition bit */ 162 1.1 christos return GET_H_COND (); 163 1.1 christos case H_CR_SPI : /* interrupt stack pointer */ 164 1.1 christos if (! GET_H_SM ()) 165 1.1 christos return CPU (h_gr[H_GR_SP]); 166 1.1 christos else 167 1.1 christos return CPU (h_cr[H_CR_SPI]); 168 1.1 christos case H_CR_SPU : /* user stack pointer */ 169 1.1 christos if (GET_H_SM ()) 170 1.1 christos return CPU (h_gr[H_GR_SP]); 171 1.1 christos else 172 1.1 christos return CPU (h_cr[H_CR_SPU]); 173 1.1 christos case H_CR_BPC : /* backup pc */ 174 1.1 christos return CPU (h_cr[H_CR_BPC]) & 0xfffffffe; 175 1.1 christos case H_CR_BBPC : /* backup backup pc */ 176 1.1 christos return CPU (h_cr[H_CR_BBPC]) & 0xfffffffe; 177 1.1 christos case 4 : /* ??? unspecified, but apparently available */ 178 1.1 christos case 5 : /* ??? unspecified, but apparently available */ 179 1.1 christos return CPU (h_cr[cr]); 180 1.1 christos default : 181 1.1 christos return 0; 182 1.1 christos } 183 1.1 christos } 184 1.1 christos 185 1.1 christos void 186 1.1 christos m32rbf_h_cr_set_handler (SIM_CPU *current_cpu, UINT cr, USI newval) 187 1.1 christos { 188 1.1 christos switch (cr) 189 1.1 christos { 190 1.1 christos case H_CR_PSW : /* psw */ 191 1.1 christos { 192 1.1 christos int old_sm = (CPU (h_psw) & 0x80) != 0; 193 1.1 christos int new_sm = (newval & 0x80) != 0; 194 1.1 christos CPU (h_bpsw) = (newval >> 8) & 0xff; 195 1.1 christos CPU (h_psw) = newval & 0xff; 196 1.1 christos SET_H_COND (newval & 1); 197 1.1 christos /* When switching stack modes, update the registers. */ 198 1.1 christos if (old_sm != new_sm) 199 1.1 christos { 200 1.1 christos if (old_sm) 201 1.1 christos { 202 1.1 christos /* Switching user -> system. */ 203 1.1 christos CPU (h_cr[H_CR_SPU]) = CPU (h_gr[H_GR_SP]); 204 1.1 christos CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPI]); 205 1.1 christos } 206 1.1 christos else 207 1.1 christos { 208 1.1 christos /* Switching system -> user. */ 209 1.1 christos CPU (h_cr[H_CR_SPI]) = CPU (h_gr[H_GR_SP]); 210 1.1 christos CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPU]); 211 1.1 christos } 212 1.1 christos } 213 1.1 christos break; 214 1.1 christos } 215 1.1 christos case H_CR_BBPSW : /* backup backup psw */ 216 1.1 christos CPU (h_bbpsw) = newval & 0xff; 217 1.1 christos break; 218 1.1 christos case H_CR_CBR : /* condition bit */ 219 1.1 christos SET_H_COND (newval & 1); 220 1.1 christos break; 221 1.1 christos case H_CR_SPI : /* interrupt stack pointer */ 222 1.1 christos if (! GET_H_SM ()) 223 1.1 christos CPU (h_gr[H_GR_SP]) = newval; 224 1.1 christos else 225 1.1 christos CPU (h_cr[H_CR_SPI]) = newval; 226 1.1 christos break; 227 1.1 christos case H_CR_SPU : /* user stack pointer */ 228 1.1 christos if (GET_H_SM ()) 229 1.1 christos CPU (h_gr[H_GR_SP]) = newval; 230 1.1 christos else 231 1.1 christos CPU (h_cr[H_CR_SPU]) = newval; 232 1.1 christos break; 233 1.1 christos case H_CR_BPC : /* backup pc */ 234 1.1 christos CPU (h_cr[H_CR_BPC]) = newval; 235 1.1 christos break; 236 1.1 christos case H_CR_BBPC : /* backup backup pc */ 237 1.1 christos CPU (h_cr[H_CR_BBPC]) = newval; 238 1.1 christos break; 239 1.1 christos case 4 : /* ??? unspecified, but apparently available */ 240 1.1 christos case 5 : /* ??? unspecified, but apparently available */ 241 1.1 christos CPU (h_cr[cr]) = newval; 242 1.1 christos break; 243 1.1 christos default : 244 1.1 christos /* ignore */ 245 1.1 christos break; 246 1.1 christos } 247 1.1 christos } 248 1.1 christos 249 1.1 christos /* Cover fns to access h-psw. */ 250 1.1 christos 251 1.1 christos UQI 252 1.1 christos m32rbf_h_psw_get_handler (SIM_CPU *current_cpu) 253 1.1 christos { 254 1.1 christos return (CPU (h_psw) & 0xfe) | (CPU (h_cond) & 1); 255 1.1 christos } 256 1.1 christos 257 1.1 christos void 258 1.1 christos m32rbf_h_psw_set_handler (SIM_CPU *current_cpu, UQI newval) 259 1.1 christos { 260 1.1 christos CPU (h_psw) = newval; 261 1.1 christos CPU (h_cond) = newval & 1; 262 1.1 christos } 263 1.1 christos 264 1.1 christos /* Cover fns to access h-accum. */ 265 1.1 christos 266 1.1 christos DI 267 1.1 christos m32rbf_h_accum_get_handler (SIM_CPU *current_cpu) 268 1.1 christos { 269 1.1 christos /* Sign extend the top 8 bits. */ 270 1.1 christos DI r; 271 1.1 christos #if 1 272 1.1 christos r = ANDDI (CPU (h_accum), MAKEDI (0xffffff, 0xffffffff)); 273 1.1 christos r = XORDI (r, MAKEDI (0x800000, 0)); 274 1.1 christos r = SUBDI (r, MAKEDI (0x800000, 0)); 275 1.1 christos #else 276 1.1 christos SI hi,lo; 277 1.1 christos r = CPU (h_accum); 278 1.1 christos hi = GETHIDI (r); 279 1.1 christos lo = GETLODI (r); 280 1.1 christos hi = ((hi & 0xffffff) ^ 0x800000) - 0x800000; 281 1.1 christos r = MAKEDI (hi, lo); 282 1.1 christos #endif 283 1.1 christos return r; 284 1.1 christos } 285 1.1 christos 286 1.1 christos void 287 1.1 christos m32rbf_h_accum_set_handler (SIM_CPU *current_cpu, DI newval) 288 1.1 christos { 289 1.1 christos CPU (h_accum) = newval; 290 1.1 christos } 291 1.1 christos 292 1.1 christos #if WITH_PROFILE_MODEL_P 294 1.1 christos 295 1.1 christos /* FIXME: Some of these should be inline or macros. Later. */ 296 1.1 christos 297 1.1 christos /* Initialize cycle counting for an insn. 298 1.1 christos FIRST_P is non-zero if this is the first insn in a set of parallel 299 1.1 christos insns. */ 300 1.1 christos 301 1.1 christos void 302 1.1 christos m32rbf_model_insn_before (SIM_CPU *cpu, int first_p) 303 1.1 christos { 304 1.1 christos M32R_MISC_PROFILE *mp = CPU_M32R_MISC_PROFILE (cpu); 305 1.1 christos mp->cti_stall = 0; 306 1.1 christos mp->load_stall = 0; 307 1.1 christos if (first_p) 308 1.1 christos { 309 1.1 christos mp->load_regs_pending = 0; 310 1.1 christos mp->biggest_cycles = 0; 311 1.1 christos } 312 1.1 christos } 313 1.1 christos 314 1.1 christos /* Record the cycles computed for an insn. 315 1.1 christos LAST_P is non-zero if this is the last insn in a set of parallel insns, 316 1.1 christos and we update the total cycle count. 317 1.1 christos CYCLES is the cycle count of the insn. */ 318 1.1 christos 319 1.1 christos void 320 1.1 christos m32rbf_model_insn_after (SIM_CPU *cpu, int last_p, int cycles) 321 1.1 christos { 322 1.1 christos PROFILE_DATA *p = CPU_PROFILE_DATA (cpu); 323 1.1 christos M32R_MISC_PROFILE *mp = CPU_M32R_MISC_PROFILE (cpu); 324 1.1 christos unsigned long total = cycles + mp->cti_stall + mp->load_stall; 325 1.1 christos 326 1.1 christos if (last_p) 327 1.1 christos { 328 1.1 christos unsigned long biggest = total > mp->biggest_cycles ? total : mp->biggest_cycles; 329 1.1 christos PROFILE_MODEL_TOTAL_CYCLES (p) += biggest; 330 1.1 christos PROFILE_MODEL_CUR_INSN_CYCLES (p) = total; 331 1.1 christos } 332 1.1 christos else 333 1.1 christos { 334 1.1 christos /* Here we take advantage of the fact that !last_p -> first_p. */ 335 1.1 christos mp->biggest_cycles = total; 336 1.1 christos PROFILE_MODEL_CUR_INSN_CYCLES (p) = total; 337 1.1 christos } 338 1.1 christos 339 1.1 christos /* Branch and load stall counts are recorded independently of the 340 1.1 christos total cycle count. */ 341 1.1 christos PROFILE_MODEL_CTI_STALL_CYCLES (p) += mp->cti_stall; 342 1.1 christos PROFILE_MODEL_LOAD_STALL_CYCLES (p) += mp->load_stall; 343 1.1 christos 344 1.1 christos mp->load_regs = mp->load_regs_pending; 345 1.1 christos } 346 1.1 christos 347 1.1 christos static INLINE void 348 1.1 christos check_load_stall (SIM_CPU *cpu, int regno) 349 1.1 christos { 350 1.1 christos UINT h_gr = CPU_M32R_MISC_PROFILE (cpu)->load_regs; 351 1.1 christos 352 1.1 christos if (regno != -1 353 1.1 christos && (h_gr & (1 << regno)) != 0) 354 1.1 christos { 355 1.1 christos CPU_M32R_MISC_PROFILE (cpu)->load_stall += 2; 356 1.1 christos if (TRACE_INSN_P (cpu)) 357 1.1 christos cgen_trace_printf (cpu, " ; Load stall of 2 cycles."); 358 1.1 christos } 359 1.1 christos } 360 1.1 christos 361 1.1 christos int 362 1.1 christos m32rbf_model_m32r_d_u_exec (SIM_CPU *cpu, const IDESC *idesc, 363 1.1 christos int unit_num, int referenced, 364 1.1 christos INT sr, INT sr2, INT dr) 365 1.1 christos { 366 1.1 christos check_load_stall (cpu, sr); 367 1.1 christos check_load_stall (cpu, sr2); 368 1.1 christos return idesc->timing->units[unit_num].done; 369 1.1 christos } 370 1.1 christos 371 1.1 christos int 372 1.1 christos m32rbf_model_m32r_d_u_cmp (SIM_CPU *cpu, const IDESC *idesc, 373 1.1 christos int unit_num, int referenced, 374 1.1 christos INT src1, INT src2) 375 1.1 christos { 376 1.1 christos check_load_stall (cpu, src1); 377 1.1 christos check_load_stall (cpu, src2); 378 1.1 christos return idesc->timing->units[unit_num].done; 379 1.1 christos } 380 1.1 christos 381 1.1 christos int 382 1.1 christos m32rbf_model_m32r_d_u_mac (SIM_CPU *cpu, const IDESC *idesc, 383 1.1 christos int unit_num, int referenced, 384 1.1 christos INT src1, INT src2) 385 1.1 christos { 386 1.1 christos check_load_stall (cpu, src1); 387 1.1 christos check_load_stall (cpu, src2); 388 1.1 christos return idesc->timing->units[unit_num].done; 389 1.1 christos } 390 1.1 christos 391 1.1 christos int 392 1.1 christos m32rbf_model_m32r_d_u_cti (SIM_CPU *cpu, const IDESC *idesc, 393 1.1 christos int unit_num, int referenced, 394 1.1 christos INT sr) 395 1.1 christos { 396 1.1 christos PROFILE_DATA *profile = CPU_PROFILE_DATA (cpu); 397 1.1 christos int taken_p = (referenced & (1 << 1)) != 0; 398 1.1 christos 399 1.1 christos check_load_stall (cpu, sr); 400 1.1 christos if (taken_p) 401 1.1 christos { 402 1.1 christos CPU_M32R_MISC_PROFILE (cpu)->cti_stall += 2; 403 1.1 christos PROFILE_MODEL_TAKEN_COUNT (profile) += 1; 404 1.1 christos } 405 1.1 christos else 406 1.1 christos PROFILE_MODEL_UNTAKEN_COUNT (profile) += 1; 407 1.1 christos return idesc->timing->units[unit_num].done; 408 1.1 christos } 409 1.1 christos 410 1.1 christos int 411 1.1 christos m32rbf_model_m32r_d_u_load (SIM_CPU *cpu, const IDESC *idesc, 412 1.1 christos int unit_num, int referenced, 413 1.1 christos INT sr, INT dr) 414 1.1 christos { 415 1.1 christos CPU_M32R_MISC_PROFILE (cpu)->load_regs_pending |= (1 << dr); 416 1.1 christos check_load_stall (cpu, sr); 417 1.1 christos return idesc->timing->units[unit_num].done; 418 1.1 christos } 419 1.1 christos 420 1.1 christos int 421 1.1 christos m32rbf_model_m32r_d_u_store (SIM_CPU *cpu, const IDESC *idesc, 422 1.1 christos int unit_num, int referenced, 423 1.1 christos INT src1, INT src2) 424 1.1 christos { 425 1.1 christos check_load_stall (cpu, src1); 426 1.1 christos check_load_stall (cpu, src2); 427 1.1 christos return idesc->timing->units[unit_num].done; 428 1.1 christos } 429 1.1 christos 430 1.1 christos int 431 1.1 christos m32rbf_model_test_u_exec (SIM_CPU *cpu, const IDESC *idesc, 432 1.1 christos int unit_num, int referenced) 433 1.1 christos { 434 1.1 christos return idesc->timing->units[unit_num].done; 435 1.1 christos } 436 437 #endif /* WITH_PROFILE_MODEL_P */ 438