OSDN Git Service

* cris/cris-tmpl.c (MY (f_model_insn_before)): Make sure only the
[pf3gnuchains/pf3gnuchains3x.git] / sim / cris / cris-tmpl.c
1 /* CRIS base simulator support code
2    Copyright (C) 2004, 2005 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     SIM_DESC sd = CPU_STATE (current_cpu);
123
124     cris_trace_printf (sd, current_cpu, "%lx ",
125                        0xffffffffUL & (unsigned long) (CPU (h_pc)));
126
127     for (i = 0; i < 15; i++)
128       cris_trace_printf (sd, current_cpu, "%lx ",
129                          0xffffffffUL
130                          & (unsigned long) (XCONCAT3(crisv,BASENUM,
131                                                      f_h_gr_get) (current_cpu,
132                                                                   i)));
133     flags[0] = GET_H_IBIT () != 0 ? 'I' : 'i';
134     flags[1] = GET_H_XBIT () != 0 ? 'X' : 'x';
135     flags[2] = GET_H_NBIT () != 0 ? 'N' : 'n';
136     flags[3] = GET_H_ZBIT () != 0 ? 'Z' : 'z';
137     flags[4] = GET_H_VBIT () != 0 ? 'V' : 'v';
138     flags[5] = GET_H_CBIT () != 0 ? 'C' : 'c';
139     flags[6] = 0;
140
141     /* Emit ACR after flags and cycle count for this insn.  */
142     if (BASENUM == 32)
143       cris_trace_printf (sd, current_cpu, "%s %d %lx\n", flags,
144                          (int)
145                          ((CPU_CRIS_MISC_PROFILE (current_cpu)
146                            ->basic_cycle_count
147                            - CPU_CRIS_PREV_MISC_PROFILE (current_cpu)
148                            ->basic_cycle_count)
149                           + (CPU_CRIS_MISC_PROFILE (current_cpu)
150                              ->unaligned_mem_dword_count
151                              - CPU_CRIS_PREV_MISC_PROFILE (current_cpu)
152                              ->unaligned_mem_dword_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)
160                          ((CPU_CRIS_MISC_PROFILE (current_cpu)
161                            ->basic_cycle_count
162                            - CPU_CRIS_PREV_MISC_PROFILE (current_cpu)
163                            ->basic_cycle_count)
164                           + (CPU_CRIS_MISC_PROFILE (current_cpu)
165                              ->unaligned_mem_dword_count
166                              - CPU_CRIS_PREV_MISC_PROFILE (current_cpu)
167                              ->unaligned_mem_dword_count)));
168
169     CPU_CRIS_PREV_MISC_PROFILE (current_cpu)[0]
170       = CPU_CRIS_MISC_PROFILE (current_cpu)[0];
171   }
172 }
173
174 /* Record the cycles computed for an insn.
175    LAST_P is non-zero if this is the last insn in a set of parallel insns,
176    and we update the total cycle count.
177    CYCLES is the cycle count of the insn.  */
178
179 void
180 MY (f_model_insn_after) (SIM_CPU *current_cpu, int last_p ATTRIBUTE_UNUSED,
181                          int cycles)
182 {
183   PROFILE_DATA *p = CPU_PROFILE_DATA (current_cpu);
184
185   PROFILE_MODEL_TOTAL_CYCLES (p) += cycles;
186   CPU_CRIS_MISC_PROFILE (current_cpu)->basic_cycle_count += cycles;
187   PROFILE_MODEL_CUR_INSN_CYCLES (p) = cycles;
188 }
189
190 /* Initialize cycle counting for an insn.
191    FIRST_P is non-zero if this is the first insn in a set of parallel
192    insns.  */
193
194 void
195 MY (f_model_init_insn_cycles) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
196                                int first_p ATTRIBUTE_UNUSED)
197 {
198   abort ();
199 }
200
201 /* Record the cycles computed for an insn.
202    LAST_P is non-zero if this is the last insn in a set of parallel insns,
203    and we update the total cycle count.  */
204
205 void
206 MY (f_model_update_insn_cycles) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
207                                  int last_p ATTRIBUTE_UNUSED)
208 {
209   abort ();
210 }
211
212 #if 0
213 void
214 MY (f_model_record_cycles) (SIM_CPU *current_cpu, unsigned long cycles)
215 {
216   abort ();
217 }
218
219 void
220 MY (f_model_mark_get_h_gr) (SIM_CPU *current_cpu, ARGBUF *abuf)
221 {
222   abort ();
223 }
224
225 void
226 MY (f_model_mark_set_h_gr) (SIM_CPU *current_cpu, ARGBUF *abuf)
227 {
228   abort ();
229 }
230 #endif
231 \f
232 /* Create the context for a thread.  */
233
234 void *
235 MY (make_thread_cpu_data) (SIM_CPU *current_cpu, void *context)
236 {
237   void *info = xmalloc (current_cpu->thread_cpu_data_size);
238
239   if (context != NULL)
240     memcpy (info,
241             context,
242             current_cpu->thread_cpu_data_size);
243   else
244     memset (info, 0, current_cpu->thread_cpu_data_size),abort();
245   return info;
246 }
247
248 /* Hook function for per-cpu simulator initialization.  */
249
250 void
251 MY (f_specific_init) (SIM_CPU *current_cpu)
252 {
253   current_cpu->make_thread_cpu_data = MY (make_thread_cpu_data);
254   current_cpu->thread_cpu_data_size = sizeof (current_cpu->cpu_data);
255 }
256 \f
257 /* Model function for arbitrary single stall cycles.  */
258
259 int
260 MY (XCONCAT3 (f_model_crisv,BASENUM,
261               _u_stall)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
262                           const IDESC *idesc,
263                           int unit_num,
264                           int referenced ATTRIBUTE_UNUSED)
265 {
266   return idesc->timing->units[unit_num].done;
267 }
268
269 #ifndef SPECIFIC_U_SKIP4_FN
270
271 /* Model function for u-skip4 unit.  */
272
273 int
274 MY (XCONCAT3 (f_model_crisv,BASENUM,
275               _u_skip4)) (SIM_CPU *current_cpu,
276                           const IDESC *idesc,
277                           int unit_num,
278                           int referenced ATTRIBUTE_UNUSED)
279 {
280   /* Handle PC not being updated with pbb.  FIXME: What if not pbb?  */
281   CPU (h_pc) += 4;
282   return idesc->timing->units[unit_num].done;
283 }
284
285 #endif
286
287 #ifndef SPECIFIC_U_EXEC_FN
288
289 /* Model function for u-exec unit.  */
290
291 int
292 MY (XCONCAT3 (f_model_crisv,BASENUM,
293               _u_exec)) (SIM_CPU *current_cpu,
294                          const IDESC *idesc,
295                          int unit_num, int referenced ATTRIBUTE_UNUSED)
296 {
297   /* Handle PC not being updated with pbb.  FIXME: What if not pbb?  */
298   CPU (h_pc) += 2;
299   return idesc->timing->units[unit_num].done;
300 }
301 #endif
302
303 #ifndef SPECIFIC_U_MEM_FN
304
305 /* Model function for u-mem unit.  */
306
307 int
308 MY (XCONCAT3 (f_model_crisv,BASENUM,
309               _u_mem)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
310                         const IDESC *idesc,
311                         int unit_num,
312                         int referenced ATTRIBUTE_UNUSED)
313 {
314   return idesc->timing->units[unit_num].done;
315 }
316 #endif
317
318 #ifndef SPECIFIC_U_CONST16_FN
319
320 /* Model function for u-const16 unit.  */
321
322 int
323 MY (XCONCAT3 (f_model_crisv,BASENUM,
324               _u_const16)) (SIM_CPU *current_cpu,
325                             const IDESC *idesc,
326                             int unit_num,
327                             int referenced ATTRIBUTE_UNUSED)
328 {
329   CPU (h_pc) += 2;
330   return idesc->timing->units[unit_num].done;
331 }
332 #endif /* SPECIFIC_U_CONST16_FN */
333
334 #ifndef SPECIFIC_U_CONST32_FN
335
336 /* This will be incorrect for early models, where a dword always take
337    two cycles.  */
338 #define CRIS_MODEL_MASK_PC_STALL 2
339
340 /* Model function for u-const32 unit.  */
341
342 int
343 MY (XCONCAT3 (f_model_crisv,BASENUM,
344               _u_const32)) (SIM_CPU *current_cpu,
345                             const IDESC *idesc,
346                             int unit_num,
347                             int referenced ATTRIBUTE_UNUSED)
348 {
349   int unaligned_extra
350     = (((CPU (h_pc) + 2) & CRIS_MODEL_MASK_PC_STALL)
351        == CRIS_MODEL_MASK_PC_STALL);
352
353   /* Handle PC not being updated with pbb.  FIXME: What if not pbb?  */
354   CPU_CRIS_MISC_PROFILE (current_cpu)->unaligned_mem_dword_count
355     += unaligned_extra;
356
357   CPU (h_pc) += 4;
358   return idesc->timing->units[unit_num].done;
359 }
360 #endif /* SPECIFIC_U_CONST32_FN */
361
362 #ifndef SPECIFIC_U_MOVEM_FN
363
364 /* Model function for u-movem unit.  */
365
366 int
367 MY (XCONCAT3 (f_model_crisv,BASENUM,
368               _u_movem)) (SIM_CPU *current_cpu ATTRIBUTE_UNUSED,
369                           const IDESC *idesc ATTRIBUTE_UNUSED,
370                           int unit_num ATTRIBUTE_UNUSED,
371                           int referenced ATTRIBUTE_UNUSED,
372                           INT limreg)
373 {
374   /* FIXME: Add cycles for misalignment.  */
375
376   if (limreg == -1)
377     abort ();
378
379   /* We don't record movem move cycles in movemsrc_stall_count since
380      those cycles have historically been handled as ordinary cycles.  */
381   return limreg + 1;
382 }
383 #endif /* SPECIFIC_U_MOVEM_FN */
384
385 #endif /* WITH_PROFILE_MODEL_P */