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