1/* m32r2 simulator support code 2 Copyright (C) 1997, 1998, 2003, 2007 Free Software Foundation, Inc. 3 Contributed by Cygnus Support. 4 5 This file is part of GDB, the GNU debugger. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20#define WANT_CPU m32r2f 21#define WANT_CPU_M32R2F 22 23#include "sim-main.h" 24#include "cgen-mem.h" 25#include "cgen-ops.h" 26 27/* The contents of BUF are in target byte order. */ 28 29int 30m32r2f_fetch_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len) 31{ 32 return m32rbf_fetch_register (current_cpu, rn, buf, len); 33} 34 35/* The contents of BUF are in target byte order. */ 36 37int 38m32r2f_store_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len) 39{ 40 return m32rbf_store_register (current_cpu, rn, buf, len); 41} 42 43/* Cover fns to get/set the control registers. 44 FIXME: Duplicated from m32r.c. The issue is structure offsets. */ 45 46USI 47m32r2f_h_cr_get_handler (SIM_CPU *current_cpu, UINT cr) 48{ 49 switch (cr) 50 { 51 case H_CR_PSW : /* PSW. */ 52 return (((CPU (h_bpsw) & 0xc1) << 8) 53 | ((CPU (h_psw) & 0xc0) << 0) 54 | GET_H_COND ()); 55 case H_CR_BBPSW : /* Backup backup psw. */ 56 return CPU (h_bbpsw) & 0xc1; 57 case H_CR_CBR : /* Condition bit. */ 58 return GET_H_COND (); 59 case H_CR_SPI : /* Interrupt stack pointer. */ 60 if (! GET_H_SM ()) 61 return CPU (h_gr[H_GR_SP]); 62 else 63 return CPU (h_cr[H_CR_SPI]); 64 case H_CR_SPU : /* User stack pointer. */ 65 if (GET_H_SM ()) 66 return CPU (h_gr[H_GR_SP]); 67 else 68 return CPU (h_cr[H_CR_SPU]); 69 case H_CR_BPC : /* Backup pc. */ 70 return CPU (h_cr[H_CR_BPC]) & 0xfffffffe; 71 case H_CR_BBPC : /* Backup backup pc. */ 72 return CPU (h_cr[H_CR_BBPC]) & 0xfffffffe; 73 case 4 : /* ??? unspecified, but apparently available */ 74 case 5 : /* ??? unspecified, but apparently available */ 75 return CPU (h_cr[cr]); 76 default : 77 return 0; 78 } 79} 80 81void 82m32r2f_h_cr_set_handler (SIM_CPU *current_cpu, UINT cr, USI newval) 83{ 84 switch (cr) 85 { 86 case H_CR_PSW : /* psw */ 87 { 88 int old_sm = (CPU (h_psw) & 0x80) != 0; 89 int new_sm = (newval & 0x80) != 0; 90 CPU (h_bpsw) = (newval >> 8) & 0xff; 91 CPU (h_psw) = newval & 0xff; 92 SET_H_COND (newval & 1); 93 /* When switching stack modes, update the registers. */ 94 if (old_sm != new_sm) 95 { 96 if (old_sm) 97 { 98 /* Switching user -> system. */ 99 CPU (h_cr[H_CR_SPU]) = CPU (h_gr[H_GR_SP]); 100 CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPI]); 101 } 102 else 103 { 104 /* Switching system -> user. */ 105 CPU (h_cr[H_CR_SPI]) = CPU (h_gr[H_GR_SP]); 106 CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPU]); 107 } 108 } 109 break; 110 } 111 case H_CR_BBPSW : /* backup backup psw */ 112 CPU (h_bbpsw) = newval & 0xff; 113 break; 114 case H_CR_CBR : /* condition bit */ 115 SET_H_COND (newval & 1); 116 break; 117 case H_CR_SPI : /* interrupt stack pointer */ 118 if (! GET_H_SM ()) 119 CPU (h_gr[H_GR_SP]) = newval; 120 else 121 CPU (h_cr[H_CR_SPI]) = newval; 122 break; 123 case H_CR_SPU : /* user stack pointer */ 124 if (GET_H_SM ()) 125 CPU (h_gr[H_GR_SP]) = newval; 126 else 127 CPU (h_cr[H_CR_SPU]) = newval; 128 break; 129 case H_CR_BPC : /* backup pc */ 130 CPU (h_cr[H_CR_BPC]) = newval; 131 break; 132 case H_CR_BBPC : /* backup backup pc */ 133 CPU (h_cr[H_CR_BBPC]) = newval; 134 break; 135 case 4 : /* ??? unspecified, but apparently available */ 136 case 5 : /* ??? unspecified, but apparently available */ 137 CPU (h_cr[cr]) = newval; 138 break; 139 default : 140 /* ignore */ 141 break; 142 } 143} 144 145/* Cover fns to access h-psw. */ 146 147UQI 148m32r2f_h_psw_get_handler (SIM_CPU *current_cpu) 149{ 150 return (CPU (h_psw) & 0xfe) | (CPU (h_cond) & 1); 151} 152 153void 154m32r2f_h_psw_set_handler (SIM_CPU *current_cpu, UQI newval) 155{ 156 CPU (h_psw) = newval; 157 CPU (h_cond) = newval & 1; 158} 159 160/* Cover fns to access h-accum. */ 161 162DI 163m32r2f_h_accum_get_handler (SIM_CPU *current_cpu) 164{ 165 /* Sign extend the top 8 bits. */ 166 DI r; 167 r = ANDDI (CPU (h_accum), MAKEDI (0xffffff, 0xffffffff)); 168 r = XORDI (r, MAKEDI (0x800000, 0)); 169 r = SUBDI (r, MAKEDI (0x800000, 0)); 170 return r; 171} 172 173void 174m32r2f_h_accum_set_handler (SIM_CPU *current_cpu, DI newval) 175{ 176 CPU (h_accum) = newval; 177} 178 179/* Cover fns to access h-accums. */ 180 181DI 182m32r2f_h_accums_get_handler (SIM_CPU *current_cpu, UINT regno) 183{ 184 /* FIXME: Yes, this is just a quick hack. */ 185 DI r; 186 if (regno == 0) 187 r = CPU (h_accum); 188 else 189 r = CPU (h_accums[1]); 190 /* Sign extend the top 8 bits. */ 191 r = ANDDI (r, MAKEDI (0xffffff, 0xffffffff)); 192 r = XORDI (r, MAKEDI (0x800000, 0)); 193 r = SUBDI (r, MAKEDI (0x800000, 0)); 194 return r; 195} 196 197void 198m32r2f_h_accums_set_handler (SIM_CPU *current_cpu, UINT regno, DI newval) 199{ 200 /* FIXME: Yes, this is just a quick hack. */ 201 if (regno == 0) 202 CPU (h_accum) = newval; 203 else 204 CPU (h_accums[1]) = newval; 205} 206 207#if WITH_PROFILE_MODEL_P 208 209/* Initialize cycle counting for an insn. 210 FIRST_P is non-zero if this is the first insn in a set of parallel 211 insns. */ 212 213void 214m32r2f_model_insn_before (SIM_CPU *cpu, int first_p) 215{ 216 m32rbf_model_insn_before (cpu, first_p); 217} 218 219/* Record the cycles computed for an insn. 220 LAST_P is non-zero if this is the last insn in a set of parallel insns, 221 and we update the total cycle count. 222 CYCLES is the cycle count of the insn. */ 223 224void 225m32r2f_model_insn_after (SIM_CPU *cpu, int last_p, int cycles) 226{ 227 m32rbf_model_insn_after (cpu, last_p, cycles); 228} 229 230static INLINE void 231check_load_stall (SIM_CPU *cpu, int regno) 232{ 233 UINT h_gr = CPU_M32R_MISC_PROFILE (cpu)->load_regs; 234 235 if (regno != -1 236 && (h_gr & (1 << regno)) != 0) 237 { 238 CPU_M32R_MISC_PROFILE (cpu)->load_stall += 2; 239 if (TRACE_INSN_P (cpu)) 240 cgen_trace_printf (cpu, " ; Load stall of 2 cycles."); 241 } 242} 243 244int 245m32r2f_model_m32r2_u_exec (SIM_CPU *cpu, const IDESC *idesc, 246 int unit_num, int referenced, 247 INT sr, INT sr2, INT dr) 248{ 249 check_load_stall (cpu, sr); 250 check_load_stall (cpu, sr2); 251 return idesc->timing->units[unit_num].done; 252} 253 254int 255m32r2f_model_m32r2_u_cmp (SIM_CPU *cpu, const IDESC *idesc, 256 int unit_num, int referenced, 257 INT src1, INT src2) 258{ 259 check_load_stall (cpu, src1); 260 check_load_stall (cpu, src2); 261 return idesc->timing->units[unit_num].done; 262} 263 264int 265m32r2f_model_m32r2_u_mac (SIM_CPU *cpu, const IDESC *idesc, 266 int unit_num, int referenced, 267 INT src1, INT src2) 268{ 269 check_load_stall (cpu, src1); 270 check_load_stall (cpu, src2); 271 return idesc->timing->units[unit_num].done; 272} 273 274int 275m32r2f_model_m32r2_u_cti (SIM_CPU *cpu, const IDESC *idesc, 276 int unit_num, int referenced, 277 INT sr) 278{ 279 PROFILE_DATA *profile = CPU_PROFILE_DATA (cpu); 280 int taken_p = (referenced & (1 << 1)) != 0; 281 282 check_load_stall (cpu, sr); 283 if (taken_p) 284 { 285 CPU_M32R_MISC_PROFILE (cpu)->cti_stall += 2; 286 PROFILE_MODEL_TAKEN_COUNT (profile) += 1; 287 } 288 else 289 PROFILE_MODEL_UNTAKEN_COUNT (profile) += 1; 290 return idesc->timing->units[unit_num].done; 291} 292 293int 294m32r2f_model_m32r2_u_load (SIM_CPU *cpu, const IDESC *idesc, 295 int unit_num, int referenced, 296 INT sr, INT dr) 297{ 298 CPU_M32R_MISC_PROFILE (cpu)->load_regs_pending |= (1 << dr); 299 return idesc->timing->units[unit_num].done; 300} 301 302int 303m32r2f_model_m32r2_u_store (SIM_CPU *cpu, const IDESC *idesc, 304 int unit_num, int referenced, 305 INT src1, INT src2) 306{ 307 return idesc->timing->units[unit_num].done; 308} 309 310#endif /* WITH_PROFILE_MODEL_P */ 311