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