OSDN Git Service

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