OSDN Git Service

Switch the license of all files explicitly copyright the FSF
[pf3gnuchains/pf3gnuchains3x.git] / sim / m32r / m32r.c
1 /* m32r simulator support code
2    Copyright (C) 1996, 1997, 1998, 2003, 2007 Free Software Foundation, Inc.
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
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
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
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/>.  */
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
29 int
30 m32r_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;
41       case EVB_REGNUM : return H_CR_CR5;
42     }
43   abort ();
44 }
45
46 /* The contents of BUF are in target byte order.  */
47
48 int
49 m32rbf_fetch_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len)
50 {
51   if (rn < 16)
52     SETTWI (buf, m32rbf_h_gr_get (current_cpu, rn));
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 :
63         SETTWI (buf, m32rbf_h_cr_get (current_cpu,
64                                       m32r_decode_gdb_ctrl_regnum (rn)));
65         break;
66       case PC_REGNUM :
67         SETTWI (buf, m32rbf_h_pc_get (current_cpu));
68         break;
69       case ACCL_REGNUM :
70         SETTWI (buf, GETLODI (m32rbf_h_accum_get (current_cpu)));
71         break;
72       case ACCH_REGNUM :
73         SETTWI (buf, GETHIDI (m32rbf_h_accum_get (current_cpu)));
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
84 int
85 m32rbf_store_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len)
86 {
87   if (rn < 16)
88     m32rbf_h_gr_set (current_cpu, rn, GETTWI (buf));
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 :
99         m32rbf_h_cr_set (current_cpu,
100                          m32r_decode_gdb_ctrl_regnum (rn),
101                          GETTWI (buf));
102         break;
103       case PC_REGNUM :
104         m32rbf_h_pc_set (current_cpu, GETTWI (buf));
105         break;
106       case ACCL_REGNUM :
107         {
108           DI val = m32rbf_h_accum_get (current_cpu);
109           SETLODI (val, GETTWI (buf));
110           m32rbf_h_accum_set (current_cpu, val);
111           break;
112         }
113       case ACCH_REGNUM :
114         {
115           DI val = m32rbf_h_accum_get (current_cpu);
116           SETHIDI (val, GETTWI (buf));
117           m32rbf_h_accum_set (current_cpu, val);
118           break;
119         }
120       default :
121         return 0;
122       }
123
124   return -1; /*FIXME*/
125 }
126 \f
127 USI
128 m32rbf_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
162 void
163 m32rbf_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
228 UQI
229 m32rbf_h_psw_get_handler (SIM_CPU *current_cpu)
230 {
231   return (CPU (h_psw) & 0xfe) | (CPU (h_cond) & 1);
232 }
233
234 void
235 m32rbf_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
243 DI
244 m32rbf_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
263 void
264 m32rbf_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
277 void
278 m32rbf_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
295 void
296 m32rbf_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
323 static INLINE void
324 check_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
337 int
338 m32rbf_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
347 int
348 m32rbf_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
357 int
358 m32rbf_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
367 int
368 m32rbf_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
386 int
387 m32rbf_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
396 int
397 m32rbf_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
406 int
407 m32rbf_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 */