OSDN Git Service

Updated copyright notices for most files.
[pf3gnuchains/pf3gnuchains3x.git] / sim / cris / cris-tmpl.c
1 /* CRIS base simulator support code
2    Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
3    Contributed by Axis Communications.
4
5 This file is part of the GNU simulators.
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 /* The infrastructure is based on that of i960.c.  */
21
22 #define WANT_CPU
23
24 #include "sim-main.h"
25 #include "cgen-mem.h"
26 #include "cgen-ops.h"
27
28 #define MY(f) XCONCAT3(crisv,BASENUM,f)
29
30 /* Dispatcher for break insn.  */
31
32 USI
33 MY (f_break_handler) (SIM_CPU *cpu, USI breaknum, USI pc)
34 {
35   SIM_DESC sd = CPU_STATE (cpu);
36   USI ret = pc + 2;
37
38   MY (f_h_pc_set) (cpu, ret);
39
40   /* FIXME: Error out if IBR or ERP set.  */
41   switch (breaknum)
42     {
43     case 13:
44       MY (f_h_gr_set (cpu, 10,
45                       cris_break_13_handler (cpu,
46                                              MY (f_h_gr_get (cpu, 9)),
47                                              MY (f_h_gr_get (cpu, 10)),
48                                              MY (f_h_gr_get (cpu, 11)),
49                                              MY (f_h_gr_get (cpu, 12)),
50                                              MY (f_h_gr_get (cpu, 13)),
51                                              MY (f_h_sr_get (cpu, 7)),
52                                              MY (f_h_sr_get (cpu, 11)),
53                                              pc)));
54       break;
55
56     case 14:
57       sim_io_printf (sd, "%x\n", MY (f_h_gr_get (cpu, 3)));
58       break;
59
60     case 15:
61       /* Re-use the Linux exit call.  */
62       cris_break_13_handler (cpu, /* TARGET_SYS_exit */ 1, 0,
63                              0, 0, 0, 0, 0, pc);
64
65     default:
66       abort ();
67     }
68
69   return MY (f_h_pc_get) (cpu);
70 }
71
72 /* Accessor function for simulator internal use.
73    Note the contents of BUF are in target byte order.  */
74
75 int
76 MY (f_fetch_register) (SIM_CPU *current_cpu, int rn,
77                       unsigned char *buf, int len ATTRIBUTE_UNUSED)
78 {
79   SETTSI (buf, XCONCAT3(crisv,BASENUM,f_h_gr_get) (current_cpu, rn));
80   return -1;
81 }
82
83 /* Accessor function for simulator internal use.
84    Note the contents of BUF are in target byte order.  */
85
86 int
87 MY (f_store_register) (SIM_CPU *current_cpu, int rn,
88                       unsigned char *buf, int len ATTRIBUTE_UNUSED)
89 {
90   XCONCAT3(crisv,BASENUM,f_h_gr_set) (current_cpu, rn, GETTSI (buf));
91   return -1;
92 }
93 \f
94 #if WITH_PROFILE_MODEL_P
95
96 /* FIXME: Some of these should be inline or macros.  Later.  */
97
98 /* Initialize cycle counting for an insn.
99    FIRST_P is non-zero if this is the first insn in a set of parallel
100    insns.  */
101
102 void
103 MY (f_model_insn_before) (SIM_CPU *current_cpu, int first_p ATTRIBUTE_UNUSED)
104 {
105   /* To give the impression that we actually know what PC is, we have to
106      dump register contents *before* the *next* insn, not after the
107      *previous* insn.  Uhh...  */
108
109   /* FIXME: Move this to separate, overridable function.  */
110   if ((CPU_CRIS_MISC_PROFILE (current_cpu)->flags
111        & FLAG_CRIS_MISC_PROFILE_XSIM_TRACE)
112 #ifdef GET_H_INSN_PREFIXED_P
113       /* For versions with prefixed insns, trace the combination as
114          one insn.  */
115       && !GET_H_INSN_PREFIXED_P ()
116 #endif
117       && 1)
118   {
119     int i;
120     char flags[7];
121     unsigned64 cycle_count;
122
123     SIM_DESC sd = CPU_STATE (current_cpu);
124
125     cris_trace_printf (sd, current_cpu, "%lx ",
126                        0xffffffffUL & (unsigned long) (CPU (h_pc)));
127
128     for (i = 0; i < 15; i++)
129       cris_trace_printf (sd, current_cpu, "%lx ",
130                          0xffffffffUL
131                          & (unsigned long) (XCONCAT3(crisv,BASENUM,
132                                                      f_h_gr_get) (current_cpu,
133                                                                   i)));
134     flags[0] = GET_H_IBIT () != 0 ? 'I' : 'i';
135     flags[1] = GET_H_XBIT () != 0 ? 'X' : 'x';
136     flags[2] = GET_H_NBIT () != 0 ? 'N' : 'n';
137     flags[3] = GET_H_ZBIT () != 0 ? 'Z' : 'z';
138     flags[4] = GET_H_VBIT () != 0 ? 'V' : 'v';
139     flags[5] = GET_H_CBIT () != 0 ? 'C' : 'c';
140     flags[6] = 0;
141
142     /* For anything else than basic tracing we'd add stall cycles for
143        e.g. unaligned accesses.  FIXME: add --cris-trace=x options to
144        match --cris-cycles=x.  */
145     cycle_count
146       = (CPU_CRIS_MISC_PROFILE (current_cpu)->basic_cycle_count
147          - CPU_CRIS_PREV_MISC_PROFILE (current_cpu)->basic_cycle_count);
148
149     /* Emit ACR after flags and cycle count for this insn.  */
150     if (BASENUM == 32)
151       cris_trace_printf (sd, current_cpu, "%s %d %lx\n", flags,
152                          (int) cycle_count,
153                          0xffffffffUL
154                          & (unsigned long) (XCONCAT3(crisv,BASENUM,
155                                                      f_h_gr_get) (current_cpu,
156                                                                   15)));
157     else
158       cris_trace_printf (sd, current_cpu, "%s %d\n", flags,
159                          (int) cycle_count);
160
161     CPU_CRIS_PREV_MISC_PROFILE (current_cpu)[0]
162       = CPU_CRIS_MISC_PROFILE (current_cpu)[0];
163   }
164 }
165
166 /* Record the cycles computed for an insn.
167    LAST_P is non-zero if this is the last insn in a set of parallel insns,
168    and we update the total cycle count.
169    CYCLES is the cycle count of the insn.  */
170
171 void
172 MY (f_model_insn_after) (SIM_CPU *current_cpu, int last_p ATTRIBUTE_UNUSED,
173                          int cycles)
174 {
175   PROFILE_DATA *p = CPU_PROFILE_DATA (current_cpu);
176
177   PROFILE_MODEL_TOTAL_CYCLES (p) += cycles;
178   CPU_CRIS_MISC_PROFILE (current_cpu)->basic_cycle_count += cycles;
179   PROFILE_MODEL_CUR_INSN_CYCLES (p) = cycles;
180
181 #if WITH_HW
182   /* For some reason, we don't get to the sim_events_tick call in
183      cgen-run.c:engine_run_1.  Besides, more than one cycle has
184      passed, so we want sim_events_tickn anyway.  The "events we want
185      to process" is usually to initiate an interrupt, but might also
186      be other events.  We can't do the former until the main loop is
187      at point where it accepts changing the PC without internal
188      inconsistency, so just set a flag and wait.  */
189   if (sim_events_tickn (CPU_STATE (current_cpu), cycles))
190     STATE_EVENTS (CPU_STATE (current_cpu))->work_pending = 1;
191 #endif
192 }
193
194 /* Initialize cycle counting for an insn.
195    FIRST_P is non-zero if this is the first insn in a set of parallel
196    insns.  */
197
198 void
199 MY (f_model_init_insn_cycles) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
200                                int first_p ATTRIBUTE_UNUSED)
201 {
202   abort ();
203 }
204
205 /* Record the cycles computed for an insn.
206    LAST_P is non-zero if this is the last insn in a set of parallel insns,
207    and we update the total cycle count.  */
208
209 void
210 MY (f_model_update_insn_cycles) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
211                                  int last_p ATTRIBUTE_UNUSED)
212 {
213   abort ();
214 }
215
216 #if 0
217 void
218 MY (f_model_record_cycles) (SIM_CPU *current_cpu, unsigned long cycles)
219 {
220   abort ();
221 }
222
223 void
224 MY (f_model_mark_get_h_gr) (SIM_CPU *current_cpu, ARGBUF *abuf)
225 {
226   abort ();
227 }
228
229 void
230 MY (f_model_mark_set_h_gr) (SIM_CPU *current_cpu, ARGBUF *abuf)
231 {
232   abort ();
233 }
234 #endif
235 \f
236 /* Create the context for a thread.  */
237
238 void *
239 MY (make_thread_cpu_data) (SIM_CPU *current_cpu, void *context)
240 {
241   void *info = xmalloc (current_cpu->thread_cpu_data_size);
242
243   if (context != NULL)
244     memcpy (info,
245             context,
246             current_cpu->thread_cpu_data_size);
247   else
248     memset (info, 0, current_cpu->thread_cpu_data_size),abort();
249   return info;
250 }
251
252 /* Hook function for per-cpu simulator initialization.  */
253
254 void
255 MY (f_specific_init) (SIM_CPU *current_cpu)
256 {
257   current_cpu->make_thread_cpu_data = MY (make_thread_cpu_data);
258   current_cpu->thread_cpu_data_size = sizeof (current_cpu->cpu_data);
259 #if WITH_HW
260   current_cpu->deliver_interrupt = MY (deliver_interrupt);
261 #endif
262 }
263 \f
264 /* Model function for arbitrary single stall cycles.  */
265
266 int
267 MY (XCONCAT3 (f_model_crisv,BASENUM,
268               _u_stall)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
269                           const IDESC *idesc,
270                           int unit_num,
271                           int referenced ATTRIBUTE_UNUSED)
272 {
273   return idesc->timing->units[unit_num].done;
274 }
275
276 #ifndef SPECIFIC_U_SKIP4_FN
277
278 /* Model function for u-skip4 unit.  */
279
280 int
281 MY (XCONCAT3 (f_model_crisv,BASENUM,
282               _u_skip4)) (SIM_CPU *current_cpu,
283                           const IDESC *idesc,
284                           int unit_num,
285                           int referenced ATTRIBUTE_UNUSED)
286 {
287   /* Handle PC not being updated with pbb.  FIXME: What if not pbb?  */
288   CPU (h_pc) += 4;
289   return idesc->timing->units[unit_num].done;
290 }
291
292 #endif
293
294 #ifndef SPECIFIC_U_EXEC_FN
295
296 /* Model function for u-exec unit.  */
297
298 int
299 MY (XCONCAT3 (f_model_crisv,BASENUM,
300               _u_exec)) (SIM_CPU *current_cpu,
301                          const IDESC *idesc,
302                          int unit_num, int referenced ATTRIBUTE_UNUSED)
303 {
304   /* Handle PC not being updated with pbb.  FIXME: What if not pbb?  */
305   CPU (h_pc) += 2;
306   return idesc->timing->units[unit_num].done;
307 }
308 #endif
309
310 #ifndef SPECIFIC_U_MEM_FN
311
312 /* Model function for u-mem unit.  */
313
314 int
315 MY (XCONCAT3 (f_model_crisv,BASENUM,
316               _u_mem)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
317                         const IDESC *idesc,
318                         int unit_num,
319                         int referenced ATTRIBUTE_UNUSED)
320 {
321   return idesc->timing->units[unit_num].done;
322 }
323 #endif
324
325 #ifndef SPECIFIC_U_CONST16_FN
326
327 /* Model function for u-const16 unit.  */
328
329 int
330 MY (XCONCAT3 (f_model_crisv,BASENUM,
331               _u_const16)) (SIM_CPU *current_cpu,
332                             const IDESC *idesc,
333                             int unit_num,
334                             int referenced ATTRIBUTE_UNUSED)
335 {
336   CPU (h_pc) += 2;
337   return idesc->timing->units[unit_num].done;
338 }
339 #endif /* SPECIFIC_U_CONST16_FN */
340
341 #ifndef SPECIFIC_U_CONST32_FN
342
343 /* This will be incorrect for early models, where a dword always take
344    two cycles.  */
345 #define CRIS_MODEL_MASK_PC_STALL 2
346
347 /* Model function for u-const32 unit.  */
348
349 int
350 MY (XCONCAT3 (f_model_crisv,BASENUM,
351               _u_const32)) (SIM_CPU *current_cpu,
352                             const IDESC *idesc,
353                             int unit_num,
354                             int referenced ATTRIBUTE_UNUSED)
355 {
356   int unaligned_extra
357     = (((CPU (h_pc) + 2) & CRIS_MODEL_MASK_PC_STALL)
358        == CRIS_MODEL_MASK_PC_STALL);
359
360   /* Handle PC not being updated with pbb.  FIXME: What if not pbb?  */
361   CPU_CRIS_MISC_PROFILE (current_cpu)->unaligned_mem_dword_count
362     += unaligned_extra;
363
364   CPU (h_pc) += 4;
365   return idesc->timing->units[unit_num].done;
366 }
367 #endif /* SPECIFIC_U_CONST32_FN */
368
369 #ifndef SPECIFIC_U_MOVEM_FN
370
371 /* Model function for u-movem unit.  */
372
373 int
374 MY (XCONCAT3 (f_model_crisv,BASENUM,
375               _u_movem)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
376                           const IDESC *idesc ATTRIBUTE_UNUSED,
377                           int unit_num ATTRIBUTE_UNUSED,
378                           int referenced ATTRIBUTE_UNUSED,
379                           INT limreg)
380 {
381   /* FIXME: Add cycles for misalignment.  */
382
383   if (limreg == -1)
384     abort ();
385
386   /* We don't record movem move cycles in movemsrc_stall_count since
387      those cycles have historically been handled as ordinary cycles.  */
388   return limreg + 1;
389 }
390 #endif /* SPECIFIC_U_MOVEM_FN */
391
392 #endif /* WITH_PROFILE_MODEL_P */