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