14e98e3e1Schristos /* m32rx simulator support code 2*05fa0856Schristos Copyright (C) 1997-2024 Free Software Foundation, Inc. 34e98e3e1Schristos Contributed by Cygnus Support. 44e98e3e1Schristos 54e98e3e1Schristos This file is part of GDB, the GNU debugger. 64e98e3e1Schristos 74e98e3e1Schristos This program is free software; you can redistribute it and/or modify 84e98e3e1Schristos it under the terms of the GNU General Public License as published by 94e98e3e1Schristos the Free Software Foundation; either version 3 of the License, or 104e98e3e1Schristos (at your option) any later version. 114e98e3e1Schristos 124e98e3e1Schristos This program is distributed in the hope that it will be useful, 134e98e3e1Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of 144e98e3e1Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 154e98e3e1Schristos GNU General Public License for more details. 164e98e3e1Schristos 174e98e3e1Schristos You should have received a copy of the GNU General Public License 184e98e3e1Schristos along with this program. If not, see <http://www.gnu.org/licenses/>. */ 194e98e3e1Schristos 204b169a6bSchristos /* This must come before any other includes. */ 214b169a6bSchristos #include "defs.h" 224b169a6bSchristos 234e98e3e1Schristos #define WANT_CPU m32rxf 244e98e3e1Schristos #define WANT_CPU_M32RXF 254e98e3e1Schristos 264e98e3e1Schristos #include "sim-main.h" 274e98e3e1Schristos #include "cgen-mem.h" 284e98e3e1Schristos #include "cgen-ops.h" 294e98e3e1Schristos 30*05fa0856Schristos #include "m32r-sim.h" 31*05fa0856Schristos 324e98e3e1Schristos /* The contents of BUF are in target byte order. */ 334e98e3e1Schristos 344e98e3e1Schristos int 354b169a6bSchristos m32rxf_fetch_register (SIM_CPU *current_cpu, int rn, void *buf, int len) 364e98e3e1Schristos { 374e98e3e1Schristos return m32rbf_fetch_register (current_cpu, rn, buf, len); 384e98e3e1Schristos } 394e98e3e1Schristos 404e98e3e1Schristos /* The contents of BUF are in target byte order. */ 414e98e3e1Schristos 424e98e3e1Schristos int 434b169a6bSchristos m32rxf_store_register (SIM_CPU *current_cpu, int rn, const void *buf, int len) 444e98e3e1Schristos { 454e98e3e1Schristos return m32rbf_store_register (current_cpu, rn, buf, len); 464e98e3e1Schristos } 474e98e3e1Schristos 484e98e3e1Schristos /* Cover fns to get/set the control registers. 494e98e3e1Schristos FIXME: Duplicated from m32r.c. The issue is structure offsets. */ 504e98e3e1Schristos 514e98e3e1Schristos USI 524e98e3e1Schristos m32rxf_h_cr_get_handler (SIM_CPU *current_cpu, UINT cr) 534e98e3e1Schristos { 544e98e3e1Schristos switch (cr) 554e98e3e1Schristos { 564e98e3e1Schristos case H_CR_PSW : /* psw */ 574e98e3e1Schristos return (((CPU (h_bpsw) & 0xc1) << 8) 584e98e3e1Schristos | ((CPU (h_psw) & 0xc0) << 0) 594e98e3e1Schristos | GET_H_COND ()); 604e98e3e1Schristos case H_CR_BBPSW : /* backup backup psw */ 614e98e3e1Schristos return CPU (h_bbpsw) & 0xc1; 624e98e3e1Schristos case H_CR_CBR : /* condition bit */ 634e98e3e1Schristos return GET_H_COND (); 644e98e3e1Schristos case H_CR_SPI : /* interrupt stack pointer */ 654e98e3e1Schristos if (! GET_H_SM ()) 664e98e3e1Schristos return CPU (h_gr[H_GR_SP]); 674e98e3e1Schristos else 684e98e3e1Schristos return CPU (h_cr[H_CR_SPI]); 694e98e3e1Schristos case H_CR_SPU : /* user stack pointer */ 704e98e3e1Schristos if (GET_H_SM ()) 714e98e3e1Schristos return CPU (h_gr[H_GR_SP]); 724e98e3e1Schristos else 734e98e3e1Schristos return CPU (h_cr[H_CR_SPU]); 744e98e3e1Schristos case H_CR_BPC : /* backup pc */ 754e98e3e1Schristos return CPU (h_cr[H_CR_BPC]) & 0xfffffffe; 764e98e3e1Schristos case H_CR_BBPC : /* backup backup pc */ 774e98e3e1Schristos return CPU (h_cr[H_CR_BBPC]) & 0xfffffffe; 784e98e3e1Schristos case 4 : /* ??? unspecified, but apparently available */ 794e98e3e1Schristos case 5 : /* ??? unspecified, but apparently available */ 804e98e3e1Schristos return CPU (h_cr[cr]); 814e98e3e1Schristos default : 824e98e3e1Schristos return 0; 834e98e3e1Schristos } 844e98e3e1Schristos } 854e98e3e1Schristos 864e98e3e1Schristos void 874e98e3e1Schristos m32rxf_h_cr_set_handler (SIM_CPU *current_cpu, UINT cr, USI newval) 884e98e3e1Schristos { 894e98e3e1Schristos switch (cr) 904e98e3e1Schristos { 914e98e3e1Schristos case H_CR_PSW : /* psw */ 924e98e3e1Schristos { 934e98e3e1Schristos int old_sm = (CPU (h_psw) & 0x80) != 0; 944e98e3e1Schristos int new_sm = (newval & 0x80) != 0; 954e98e3e1Schristos CPU (h_bpsw) = (newval >> 8) & 0xff; 964e98e3e1Schristos CPU (h_psw) = newval & 0xff; 974e98e3e1Schristos SET_H_COND (newval & 1); 984e98e3e1Schristos /* When switching stack modes, update the registers. */ 994e98e3e1Schristos if (old_sm != new_sm) 1004e98e3e1Schristos { 1014e98e3e1Schristos if (old_sm) 1024e98e3e1Schristos { 1034e98e3e1Schristos /* Switching user -> system. */ 1044e98e3e1Schristos CPU (h_cr[H_CR_SPU]) = CPU (h_gr[H_GR_SP]); 1054e98e3e1Schristos CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPI]); 1064e98e3e1Schristos } 1074e98e3e1Schristos else 1084e98e3e1Schristos { 1094e98e3e1Schristos /* Switching system -> user. */ 1104e98e3e1Schristos CPU (h_cr[H_CR_SPI]) = CPU (h_gr[H_GR_SP]); 1114e98e3e1Schristos CPU (h_gr[H_GR_SP]) = CPU (h_cr[H_CR_SPU]); 1124e98e3e1Schristos } 1134e98e3e1Schristos } 1144e98e3e1Schristos break; 1154e98e3e1Schristos } 1164e98e3e1Schristos case H_CR_BBPSW : /* backup backup psw */ 1174e98e3e1Schristos CPU (h_bbpsw) = newval & 0xff; 1184e98e3e1Schristos break; 1194e98e3e1Schristos case H_CR_CBR : /* condition bit */ 1204e98e3e1Schristos SET_H_COND (newval & 1); 1214e98e3e1Schristos break; 1224e98e3e1Schristos case H_CR_SPI : /* interrupt stack pointer */ 1234e98e3e1Schristos if (! GET_H_SM ()) 1244e98e3e1Schristos CPU (h_gr[H_GR_SP]) = newval; 1254e98e3e1Schristos else 1264e98e3e1Schristos CPU (h_cr[H_CR_SPI]) = newval; 1274e98e3e1Schristos break; 1284e98e3e1Schristos case H_CR_SPU : /* user stack pointer */ 1294e98e3e1Schristos if (GET_H_SM ()) 1304e98e3e1Schristos CPU (h_gr[H_GR_SP]) = newval; 1314e98e3e1Schristos else 1324e98e3e1Schristos CPU (h_cr[H_CR_SPU]) = newval; 1334e98e3e1Schristos break; 1344e98e3e1Schristos case H_CR_BPC : /* backup pc */ 1354e98e3e1Schristos CPU (h_cr[H_CR_BPC]) = newval; 1364e98e3e1Schristos break; 1374e98e3e1Schristos case H_CR_BBPC : /* backup backup pc */ 1384e98e3e1Schristos CPU (h_cr[H_CR_BBPC]) = newval; 1394e98e3e1Schristos break; 1404e98e3e1Schristos case 4 : /* ??? unspecified, but apparently available */ 1414e98e3e1Schristos case 5 : /* ??? unspecified, but apparently available */ 1424e98e3e1Schristos CPU (h_cr[cr]) = newval; 1434e98e3e1Schristos break; 1444e98e3e1Schristos default : 1454e98e3e1Schristos /* ignore */ 1464e98e3e1Schristos break; 1474e98e3e1Schristos } 1484e98e3e1Schristos } 1494e98e3e1Schristos 1504e98e3e1Schristos /* Cover fns to access h-psw. */ 1514e98e3e1Schristos 1524e98e3e1Schristos UQI 1534e98e3e1Schristos m32rxf_h_psw_get_handler (SIM_CPU *current_cpu) 1544e98e3e1Schristos { 1554e98e3e1Schristos return (CPU (h_psw) & 0xfe) | (CPU (h_cond) & 1); 1564e98e3e1Schristos } 1574e98e3e1Schristos 1584e98e3e1Schristos void 1594e98e3e1Schristos m32rxf_h_psw_set_handler (SIM_CPU *current_cpu, UQI newval) 1604e98e3e1Schristos { 1614e98e3e1Schristos CPU (h_psw) = newval; 1624e98e3e1Schristos CPU (h_cond) = newval & 1; 1634e98e3e1Schristos } 1644e98e3e1Schristos 1654e98e3e1Schristos /* Cover fns to access h-accum. */ 1664e98e3e1Schristos 1674e98e3e1Schristos DI 1684e98e3e1Schristos m32rxf_h_accum_get_handler (SIM_CPU *current_cpu) 1694e98e3e1Schristos { 1704e98e3e1Schristos /* Sign extend the top 8 bits. */ 1714e98e3e1Schristos DI r; 1724e98e3e1Schristos r = ANDDI (CPU (h_accum), MAKEDI (0xffffff, 0xffffffff)); 1734e98e3e1Schristos r = XORDI (r, MAKEDI (0x800000, 0)); 1744e98e3e1Schristos r = SUBDI (r, MAKEDI (0x800000, 0)); 1754e98e3e1Schristos return r; 1764e98e3e1Schristos } 1774e98e3e1Schristos 1784e98e3e1Schristos void 1794e98e3e1Schristos m32rxf_h_accum_set_handler (SIM_CPU *current_cpu, DI newval) 1804e98e3e1Schristos { 1814e98e3e1Schristos CPU (h_accum) = newval; 1824e98e3e1Schristos } 1834e98e3e1Schristos 1844e98e3e1Schristos /* Cover fns to access h-accums. */ 1854e98e3e1Schristos 1864e98e3e1Schristos DI 1874e98e3e1Schristos m32rxf_h_accums_get_handler (SIM_CPU *current_cpu, UINT regno) 1884e98e3e1Schristos { 1894e98e3e1Schristos /* FIXME: Yes, this is just a quick hack. */ 1904e98e3e1Schristos DI r; 1914e98e3e1Schristos if (regno == 0) 1924e98e3e1Schristos r = CPU (h_accum); 1934e98e3e1Schristos else 1944e98e3e1Schristos r = CPU (h_accums[1]); 1954e98e3e1Schristos /* Sign extend the top 8 bits. */ 1964e98e3e1Schristos r = ANDDI (r, MAKEDI (0xffffff, 0xffffffff)); 1974e98e3e1Schristos r = XORDI (r, MAKEDI (0x800000, 0)); 1984e98e3e1Schristos r = SUBDI (r, MAKEDI (0x800000, 0)); 1994e98e3e1Schristos return r; 2004e98e3e1Schristos } 2014e98e3e1Schristos 2024e98e3e1Schristos void 2034e98e3e1Schristos m32rxf_h_accums_set_handler (SIM_CPU *current_cpu, UINT regno, DI newval) 2044e98e3e1Schristos { 2054e98e3e1Schristos /* FIXME: Yes, this is just a quick hack. */ 2064e98e3e1Schristos if (regno == 0) 2074e98e3e1Schristos CPU (h_accum) = newval; 2084e98e3e1Schristos else 2094e98e3e1Schristos CPU (h_accums[1]) = newval; 2104e98e3e1Schristos } 2114e98e3e1Schristos 2124e98e3e1Schristos #if WITH_PROFILE_MODEL_P 2134e98e3e1Schristos 2144e98e3e1Schristos /* Initialize cycle counting for an insn. 2154e98e3e1Schristos FIRST_P is non-zero if this is the first insn in a set of parallel 2164e98e3e1Schristos insns. */ 2174e98e3e1Schristos 2184e98e3e1Schristos void 2194e98e3e1Schristos m32rxf_model_insn_before (SIM_CPU *cpu, int first_p) 2204e98e3e1Schristos { 2214e98e3e1Schristos m32rbf_model_insn_before (cpu, first_p); 2224e98e3e1Schristos } 2234e98e3e1Schristos 2244e98e3e1Schristos /* Record the cycles computed for an insn. 2254e98e3e1Schristos LAST_P is non-zero if this is the last insn in a set of parallel insns, 2264e98e3e1Schristos and we update the total cycle count. 2274e98e3e1Schristos CYCLES is the cycle count of the insn. */ 2284e98e3e1Schristos 2294e98e3e1Schristos void 2304e98e3e1Schristos m32rxf_model_insn_after (SIM_CPU *cpu, int last_p, int cycles) 2314e98e3e1Schristos { 2324e98e3e1Schristos m32rbf_model_insn_after (cpu, last_p, cycles); 2334e98e3e1Schristos } 2344e98e3e1Schristos 2354e98e3e1Schristos static INLINE void 2364e98e3e1Schristos check_load_stall (SIM_CPU *cpu, int regno) 2374e98e3e1Schristos { 2384e98e3e1Schristos UINT h_gr = CPU_M32R_MISC_PROFILE (cpu)->load_regs; 2394e98e3e1Schristos 2404e98e3e1Schristos if (regno != -1 2414e98e3e1Schristos && (h_gr & (1 << regno)) != 0) 2424e98e3e1Schristos { 2434e98e3e1Schristos CPU_M32R_MISC_PROFILE (cpu)->load_stall += 2; 2444e98e3e1Schristos if (TRACE_INSN_P (cpu)) 2454e98e3e1Schristos cgen_trace_printf (cpu, " ; Load stall of 2 cycles."); 2464e98e3e1Schristos } 2474e98e3e1Schristos } 2484e98e3e1Schristos 2494e98e3e1Schristos int 2504e98e3e1Schristos m32rxf_model_m32rx_u_exec (SIM_CPU *cpu, const IDESC *idesc, 2514e98e3e1Schristos int unit_num, int referenced, 2524e98e3e1Schristos INT sr, INT sr2, INT dr) 2534e98e3e1Schristos { 2544e98e3e1Schristos check_load_stall (cpu, sr); 2554e98e3e1Schristos check_load_stall (cpu, sr2); 2564e98e3e1Schristos return idesc->timing->units[unit_num].done; 2574e98e3e1Schristos } 2584e98e3e1Schristos 2594e98e3e1Schristos int 2604e98e3e1Schristos m32rxf_model_m32rx_u_cmp (SIM_CPU *cpu, const IDESC *idesc, 2614e98e3e1Schristos int unit_num, int referenced, 2624e98e3e1Schristos INT src1, INT src2) 2634e98e3e1Schristos { 2644e98e3e1Schristos check_load_stall (cpu, src1); 2654e98e3e1Schristos check_load_stall (cpu, src2); 2664e98e3e1Schristos return idesc->timing->units[unit_num].done; 2674e98e3e1Schristos } 2684e98e3e1Schristos 2694e98e3e1Schristos int 2704e98e3e1Schristos m32rxf_model_m32rx_u_mac (SIM_CPU *cpu, const IDESC *idesc, 2714e98e3e1Schristos int unit_num, int referenced, 2724e98e3e1Schristos INT src1, INT src2) 2734e98e3e1Schristos { 2744e98e3e1Schristos check_load_stall (cpu, src1); 2754e98e3e1Schristos check_load_stall (cpu, src2); 2764e98e3e1Schristos return idesc->timing->units[unit_num].done; 2774e98e3e1Schristos } 2784e98e3e1Schristos 2794e98e3e1Schristos int 2804e98e3e1Schristos m32rxf_model_m32rx_u_cti (SIM_CPU *cpu, const IDESC *idesc, 2814e98e3e1Schristos int unit_num, int referenced, 2824e98e3e1Schristos INT sr) 2834e98e3e1Schristos { 2844e98e3e1Schristos PROFILE_DATA *profile = CPU_PROFILE_DATA (cpu); 2854e98e3e1Schristos int taken_p = (referenced & (1 << 1)) != 0; 2864e98e3e1Schristos 2874e98e3e1Schristos check_load_stall (cpu, sr); 2884e98e3e1Schristos if (taken_p) 2894e98e3e1Schristos { 2904e98e3e1Schristos CPU_M32R_MISC_PROFILE (cpu)->cti_stall += 2; 2914e98e3e1Schristos PROFILE_MODEL_TAKEN_COUNT (profile) += 1; 2924e98e3e1Schristos } 2934e98e3e1Schristos else 2944e98e3e1Schristos PROFILE_MODEL_UNTAKEN_COUNT (profile) += 1; 2954e98e3e1Schristos return idesc->timing->units[unit_num].done; 2964e98e3e1Schristos } 2974e98e3e1Schristos 2984e98e3e1Schristos int 2994e98e3e1Schristos m32rxf_model_m32rx_u_load (SIM_CPU *cpu, const IDESC *idesc, 3004e98e3e1Schristos int unit_num, int referenced, 3014e98e3e1Schristos INT sr, INT dr) 3024e98e3e1Schristos { 3034e98e3e1Schristos CPU_M32R_MISC_PROFILE (cpu)->load_regs_pending |= (1 << dr); 3044e98e3e1Schristos return idesc->timing->units[unit_num].done; 3054e98e3e1Schristos } 3064e98e3e1Schristos 3074e98e3e1Schristos int 3084e98e3e1Schristos m32rxf_model_m32rx_u_store (SIM_CPU *cpu, const IDESC *idesc, 3094e98e3e1Schristos int unit_num, int referenced, 3104e98e3e1Schristos INT src1, INT src2) 3114e98e3e1Schristos { 3124e98e3e1Schristos return idesc->timing->units[unit_num].done; 3134e98e3e1Schristos } 3144e98e3e1Schristos 3154e98e3e1Schristos #endif /* WITH_PROFILE_MODEL_P */ 316