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