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