crisv32f.c revision 1.1 1 1.1 christos /* CRIS v32 simulator support code
2 1.1 christos Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
3 1.1 christos Free Software Foundation, Inc.
4 1.1 christos Contributed by Axis Communications.
5 1.1 christos
6 1.1 christos This file is part of the GNU simulators.
7 1.1 christos
8 1.1 christos This program is free software; you can redistribute it and/or modify
9 1.1 christos it under the terms of the GNU General Public License as published by
10 1.1 christos the Free Software Foundation; either version 3 of the License, or
11 1.1 christos (at your option) any later version.
12 1.1 christos
13 1.1 christos This program is distributed in the hope that it will be useful,
14 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
15 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 1.1 christos GNU General Public License for more details.
17 1.1 christos
18 1.1 christos You should have received a copy of the GNU General Public License
19 1.1 christos along with this program. If not, see <http://www.gnu.org/licenses/>. */
20 1.1 christos
21 1.1 christos /* The infrastructure is based on that of i960.c. */
22 1.1 christos
23 1.1 christos #define WANT_CPU_CRISV32F
24 1.1 christos
25 1.1 christos #define SPECIFIC_U_EXEC_FN
26 1.1 christos #define SPECIFIC_U_SKIP4_FN
27 1.1 christos #define SPECIFIC_U_CONST16_FN
28 1.1 christos #define SPECIFIC_U_CONST32_FN
29 1.1 christos #define SPECIFIC_U_MEM_FN
30 1.1 christos #define SPECIFIC_U_MOVEM_FN
31 1.1 christos #define BASENUM 32
32 1.1 christos #define CRIS_TLS_REGISTER 2
33 1.1 christos #include "cris-tmpl.c"
34 1.1 christos
35 1.1 christos #if WITH_PROFILE_MODEL_P
36 1.1 christos
37 1.1 christos /* Re-use the bit position for the BZ register, since there are no stall
38 1.1 christos cycles for reading or writing it. */
39 1.1 christos #define CRIS_BZ_REGNO 16
40 1.1 christos #define CRIS_MODF_JUMP_MASK (1 << CRIS_BZ_REGNO)
41 1.1 christos /* Likewise for the WZ register, marking memory writes. */
42 1.1 christos #define CRIS_WZ_REGNO 20
43 1.1 christos #define CRIS_MODF_MEM_WRITE_MASK (1 << CRIS_WZ_REGNO)
44 1.1 christos #define CRIS_MOF_REGNO (16 + 7)
45 1.1 christos #define CRIS_ALWAYS_CONDITION 14
46 1.1 christos
47 1.1 christos /* This macro must only be used in context where there's only one
48 1.1 christos dynamic cause for a penalty, except in the u-exec unit. */
49 1.1 christos
50 1.1 christos #define PENALIZE1(CNT) \
51 1.1 christos do \
52 1.1 christos { \
53 1.1 christos CPU_CRIS_MISC_PROFILE (current_cpu)->CNT++; \
54 1.1 christos model_data->prev_prev_prev_modf_regs \
55 1.1 christos = model_data->prev_prev_modf_regs; \
56 1.1 christos model_data->prev_prev_modf_regs \
57 1.1 christos = model_data->prev_modf_regs; \
58 1.1 christos model_data->prev_modf_regs = 0; \
59 1.1 christos model_data->prev_prev_prev_movem_dest_regs \
60 1.1 christos = model_data->prev_prev_movem_dest_regs; \
61 1.1 christos model_data->prev_prev_movem_dest_regs \
62 1.1 christos = model_data->prev_movem_dest_regs; \
63 1.1 christos model_data->prev_movem_dest_regs = 0; \
64 1.1 christos } \
65 1.1 christos while (0)
66 1.1 christos
67 1.1 christos
68 1.1 christos /* Model function for u-skip4 unit. */
69 1.1 christos
70 1.1 christos int
71 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
72 1.1 christos _u_skip4)) (SIM_CPU *current_cpu,
73 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
74 1.1 christos int unit_num ATTRIBUTE_UNUSED,
75 1.1 christos int referenced ATTRIBUTE_UNUSED)
76 1.1 christos {
77 1.1 christos /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
78 1.1 christos CPU (h_pc) += 4;
79 1.1 christos return 0;
80 1.1 christos }
81 1.1 christos
82 1.1 christos /* Model function for u-exec unit. */
83 1.1 christos
84 1.1 christos int
85 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
86 1.1 christos _u_exec)) (SIM_CPU *current_cpu,
87 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
88 1.1 christos int unit_num ATTRIBUTE_UNUSED,
89 1.1 christos int referenced ATTRIBUTE_UNUSED,
90 1.1 christos INT destreg_in,
91 1.1 christos INT srcreg,
92 1.1 christos INT destreg_out)
93 1.1 christos {
94 1.1 christos MODEL_CRISV32_DATA *model_data
95 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
96 1.1 christos UINT modf_regs
97 1.1 christos = ((destreg_out == -1 ? 0 : (1 << destreg_out))
98 1.1 christos | model_data->modf_regs);
99 1.1 christos
100 1.1 christos if (srcreg != -1)
101 1.1 christos {
102 1.1 christos if (model_data->prev_movem_dest_regs & (1 << srcreg))
103 1.1 christos {
104 1.1 christos PENALIZE1 (movemdst_stall_count);
105 1.1 christos PENALIZE1 (movemdst_stall_count);
106 1.1 christos PENALIZE1 (movemdst_stall_count);
107 1.1 christos }
108 1.1 christos else if (model_data->prev_prev_movem_dest_regs & (1 << srcreg))
109 1.1 christos {
110 1.1 christos PENALIZE1 (movemdst_stall_count);
111 1.1 christos PENALIZE1 (movemdst_stall_count);
112 1.1 christos }
113 1.1 christos else if (model_data->prev_prev_prev_movem_dest_regs & (1 << srcreg))
114 1.1 christos PENALIZE1 (movemdst_stall_count);
115 1.1 christos }
116 1.1 christos
117 1.1 christos if (destreg_in != -1)
118 1.1 christos {
119 1.1 christos if (model_data->prev_movem_dest_regs & (1 << destreg_in))
120 1.1 christos {
121 1.1 christos PENALIZE1 (movemdst_stall_count);
122 1.1 christos PENALIZE1 (movemdst_stall_count);
123 1.1 christos PENALIZE1 (movemdst_stall_count);
124 1.1 christos }
125 1.1 christos else if (model_data->prev_prev_movem_dest_regs & (1 << destreg_in))
126 1.1 christos {
127 1.1 christos PENALIZE1 (movemdst_stall_count);
128 1.1 christos PENALIZE1 (movemdst_stall_count);
129 1.1 christos }
130 1.1 christos else if (model_data->prev_prev_prev_movem_dest_regs & (1 << destreg_in))
131 1.1 christos PENALIZE1 (movemdst_stall_count);
132 1.1 christos }
133 1.1 christos
134 1.1 christos model_data->prev_prev_prev_modf_regs
135 1.1 christos = model_data->prev_prev_modf_regs;
136 1.1 christos model_data->prev_prev_modf_regs = model_data->prev_modf_regs;
137 1.1 christos model_data->prev_modf_regs = modf_regs;
138 1.1 christos model_data->modf_regs = 0;
139 1.1 christos
140 1.1 christos model_data->prev_prev_prev_movem_dest_regs
141 1.1 christos = model_data->prev_prev_movem_dest_regs;
142 1.1 christos model_data->prev_prev_movem_dest_regs = model_data->prev_movem_dest_regs;
143 1.1 christos model_data->prev_movem_dest_regs = model_data->movem_dest_regs;
144 1.1 christos model_data->movem_dest_regs = 0;
145 1.1 christos
146 1.1 christos /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
147 1.1 christos CPU (h_pc) += 2;
148 1.1 christos return 1;
149 1.1 christos }
150 1.1 christos
151 1.1 christos /* Special case used when the destination is a special register. */
152 1.1 christos
153 1.1 christos int
154 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
155 1.1 christos _u_exec_to_sr)) (SIM_CPU *current_cpu,
156 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
157 1.1 christos int unit_num ATTRIBUTE_UNUSED,
158 1.1 christos int referenced ATTRIBUTE_UNUSED,
159 1.1 christos INT srcreg,
160 1.1 christos INT specreg)
161 1.1 christos {
162 1.1 christos int specdest;
163 1.1 christos
164 1.1 christos if (specreg != -1)
165 1.1 christos specdest = specreg + 16;
166 1.1 christos else
167 1.1 christos abort ();
168 1.1 christos
169 1.1 christos return MY (XCONCAT3 (f_model_crisv,BASENUM,_u_exec))
170 1.1 christos (current_cpu, NULL, 0, 0, -1, srcreg,
171 1.1 christos /* The positions for constant-zero registers BZ and WZ are recycled
172 1.1 christos for jump and memory-write markers. We must take precautions
173 1.1 christos here not to add false markers for them. It might be that the
174 1.1 christos hardware inserts stall cycles for instructions that actually try
175 1.1 christos and write those registers, but we'll burn that bridge when we
176 1.1 christos get to it; we'd have to find other free bits or make new
177 1.1 christos model_data variables. However, it's doubtful that there will
178 1.1 christos ever be a need to be cycle-correct for useless code, at least in
179 1.1 christos this particular simulator, mainly used for GCC testing. */
180 1.1 christos specdest == CRIS_BZ_REGNO || specdest == CRIS_WZ_REGNO
181 1.1 christos ? -1 : specdest);
182 1.1 christos }
183 1.1 christos
184 1.1 christos
185 1.1 christos /* Special case for movem. */
186 1.1 christos
187 1.1 christos int
188 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
189 1.1 christos _u_exec_movem)) (SIM_CPU *current_cpu,
190 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
191 1.1 christos int unit_num ATTRIBUTE_UNUSED,
192 1.1 christos int referenced ATTRIBUTE_UNUSED,
193 1.1 christos INT srcreg,
194 1.1 christos INT destreg_out)
195 1.1 christos {
196 1.1 christos return MY (XCONCAT3 (f_model_crisv,BASENUM,_u_exec))
197 1.1 christos (current_cpu, NULL, 0, 0, -1, srcreg, destreg_out);
198 1.1 christos }
199 1.1 christos
200 1.1 christos /* Model function for u-const16 unit. */
201 1.1 christos
202 1.1 christos int
203 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
204 1.1 christos _u_const16)) (SIM_CPU *current_cpu,
205 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
206 1.1 christos int unit_num ATTRIBUTE_UNUSED,
207 1.1 christos int referenced ATTRIBUTE_UNUSED)
208 1.1 christos {
209 1.1 christos MODEL_CRISV32_DATA *model_data
210 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
211 1.1 christos
212 1.1 christos /* If the previous insn was a jump of some sort and this insn
213 1.1 christos straddles a cache-line, there's a one-cycle penalty.
214 1.1 christos FIXME: Test-cases for normal const16 and others, like branch. */
215 1.1 christos if ((model_data->prev_modf_regs & CRIS_MODF_JUMP_MASK)
216 1.1 christos && (CPU (h_pc) & 0x1e) == 0x1e)
217 1.1 christos PENALIZE1 (jumptarget_stall_count);
218 1.1 christos
219 1.1 christos /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
220 1.1 christos CPU (h_pc) += 2;
221 1.1 christos
222 1.1 christos return 0;
223 1.1 christos }
224 1.1 christos
225 1.1 christos /* Model function for u-const32 unit. */
226 1.1 christos
227 1.1 christos int
228 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
229 1.1 christos _u_const32)) (SIM_CPU *current_cpu,
230 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
231 1.1 christos int unit_num ATTRIBUTE_UNUSED,
232 1.1 christos int referenced ATTRIBUTE_UNUSED)
233 1.1 christos {
234 1.1 christos MODEL_CRISV32_DATA *model_data
235 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
236 1.1 christos
237 1.1 christos /* If the previous insn was a jump of some sort and this insn
238 1.1 christos straddles a cache-line, there's a one-cycle penalty. */
239 1.1 christos if ((model_data->prev_modf_regs & CRIS_MODF_JUMP_MASK)
240 1.1 christos && (CPU (h_pc) & 0x1e) == 0x1c)
241 1.1 christos PENALIZE1 (jumptarget_stall_count);
242 1.1 christos
243 1.1 christos /* Handle PC not being updated with pbb. FIXME: What if not pbb? */
244 1.1 christos CPU (h_pc) += 4;
245 1.1 christos
246 1.1 christos return 0;
247 1.1 christos }
248 1.1 christos
249 1.1 christos /* Model function for u-mem unit. */
250 1.1 christos
251 1.1 christos int
252 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
253 1.1 christos _u_mem)) (SIM_CPU *current_cpu,
254 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
255 1.1 christos int unit_num ATTRIBUTE_UNUSED,
256 1.1 christos int referenced ATTRIBUTE_UNUSED,
257 1.1 christos INT srcreg)
258 1.1 christos {
259 1.1 christos MODEL_CRISV32_DATA *model_data
260 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
261 1.1 christos
262 1.1 christos if (srcreg == -1)
263 1.1 christos abort ();
264 1.1 christos
265 1.1 christos /* If srcreg references a register modified in the previous cycle
266 1.1 christos through other than autoincrement, then there's a penalty: one
267 1.1 christos cycle. */
268 1.1 christos if (model_data->prev_modf_regs & (1 << srcreg))
269 1.1 christos PENALIZE1 (memsrc_stall_count);
270 1.1 christos
271 1.1 christos return 0;
272 1.1 christos }
273 1.1 christos
274 1.1 christos /* Model function for u-mem-r unit. */
275 1.1 christos
276 1.1 christos int
277 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
278 1.1 christos _u_mem_r)) (SIM_CPU *current_cpu,
279 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
280 1.1 christos int unit_num ATTRIBUTE_UNUSED,
281 1.1 christos int referenced ATTRIBUTE_UNUSED)
282 1.1 christos {
283 1.1 christos MODEL_CRISV32_DATA *model_data
284 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
285 1.1 christos
286 1.1 christos /* There's a two-cycle penalty for read after a memory write in any of
287 1.1 christos the two previous cycles, known as a cache read-after-write hazard.
288 1.1 christos
289 1.1 christos This model function (the model_data member access) depends on being
290 1.1 christos executed before the u-exec unit. */
291 1.1 christos if ((model_data->prev_modf_regs & CRIS_MODF_MEM_WRITE_MASK)
292 1.1 christos || (model_data->prev_prev_modf_regs & CRIS_MODF_MEM_WRITE_MASK))
293 1.1 christos {
294 1.1 christos PENALIZE1 (memraw_stall_count);
295 1.1 christos PENALIZE1 (memraw_stall_count);
296 1.1 christos }
297 1.1 christos
298 1.1 christos return 0;
299 1.1 christos }
300 1.1 christos
301 1.1 christos /* Model function for u-mem-w unit. */
302 1.1 christos
303 1.1 christos int
304 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
305 1.1 christos _u_mem_w)) (SIM_CPU *current_cpu,
306 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
307 1.1 christos int unit_num ATTRIBUTE_UNUSED,
308 1.1 christos int referenced ATTRIBUTE_UNUSED)
309 1.1 christos {
310 1.1 christos MODEL_CRISV32_DATA *model_data
311 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
312 1.1 christos
313 1.1 christos /* Mark that memory has been written. This model function (the
314 1.1 christos model_data member access) depends on being executed after the
315 1.1 christos u-exec unit. */
316 1.1 christos model_data->prev_modf_regs |= CRIS_MODF_MEM_WRITE_MASK;
317 1.1 christos
318 1.1 christos return 0;
319 1.1 christos }
320 1.1 christos
321 1.1 christos /* Model function for u-movem-rtom unit. */
322 1.1 christos
323 1.1 christos int
324 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
325 1.1 christos _u_movem_rtom)) (SIM_CPU *current_cpu,
326 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
327 1.1 christos int unit_num ATTRIBUTE_UNUSED,
328 1.1 christos int referenced ATTRIBUTE_UNUSED,
329 1.1 christos /* Deliberate order. */
330 1.1 christos INT addrreg, INT limreg)
331 1.1 christos {
332 1.1 christos USI addr;
333 1.1 christos MODEL_CRISV32_DATA *model_data
334 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
335 1.1 christos
336 1.1 christos if (limreg == -1 || addrreg == -1)
337 1.1 christos abort ();
338 1.1 christos
339 1.1 christos addr = GET_H_GR (addrreg);
340 1.1 christos
341 1.1 christos /* The movem-to-memory instruction must not move a register modified
342 1.1 christos in one of the previous two cycles. Enforce by adding penalty
343 1.1 christos cycles. */
344 1.1 christos if (model_data->prev_modf_regs & ((1 << (limreg + 1)) - 1))
345 1.1 christos {
346 1.1 christos PENALIZE1 (movemsrc_stall_count);
347 1.1 christos PENALIZE1 (movemsrc_stall_count);
348 1.1 christos }
349 1.1 christos else if (model_data->prev_prev_modf_regs & ((1 << (limreg + 1)) - 1))
350 1.1 christos PENALIZE1 (movemsrc_stall_count);
351 1.1 christos
352 1.1 christos /* One-cycle penalty for each cache-line straddled. Use the
353 1.1 christos documented expressions. Unfortunately no penalty cycles are
354 1.1 christos eliminated by any penalty cycles above. We file these numbers
355 1.1 christos separately, since they aren't schedulable for all cases. */
356 1.1 christos if ((addr >> 5) == (((addr + 4 * (limreg + 1)) - 1) >> 5))
357 1.1 christos ;
358 1.1 christos else if ((addr >> 5) == (((addr + 4 * (limreg + 1)) - 1) >> 5) - 1)
359 1.1 christos PENALIZE1 (movemaddr_stall_count);
360 1.1 christos else if ((addr >> 5) == (((addr + 4 * (limreg + 1)) - 1) >> 5) - 2)
361 1.1 christos {
362 1.1 christos PENALIZE1 (movemaddr_stall_count);
363 1.1 christos PENALIZE1 (movemaddr_stall_count);
364 1.1 christos }
365 1.1 christos else
366 1.1 christos abort ();
367 1.1 christos
368 1.1 christos return 0;
369 1.1 christos }
370 1.1 christos
371 1.1 christos /* Model function for u-movem-mtor unit. */
372 1.1 christos
373 1.1 christos int
374 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
375 1.1 christos _u_movem_mtor)) (SIM_CPU *current_cpu,
376 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
377 1.1 christos int unit_num ATTRIBUTE_UNUSED,
378 1.1 christos int referenced ATTRIBUTE_UNUSED,
379 1.1 christos /* Deliberate order. */
380 1.1 christos INT addrreg, INT limreg)
381 1.1 christos {
382 1.1 christos USI addr;
383 1.1 christos int nregs = limreg + 1;
384 1.1 christos MODEL_CRISV32_DATA *model_data
385 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
386 1.1 christos
387 1.1 christos if (limreg == -1 || addrreg == -1)
388 1.1 christos abort ();
389 1.1 christos
390 1.1 christos addr = GET_H_GR (addrreg);
391 1.1 christos
392 1.1 christos /* One-cycle penalty for each cache-line straddled. Use the
393 1.1 christos documented expressions. One cycle is the norm; more cycles are
394 1.1 christos counted as penalties. Unfortunately no penalty cycles here
395 1.1 christos eliminate penalty cycles indicated in ->movem_dest_regs. */
396 1.1 christos if ((addr >> 5) == (((addr + 4 * nregs) - 1) >> 5) - 1)
397 1.1 christos PENALIZE1 (movemaddr_stall_count);
398 1.1 christos else if ((addr >> 5) == (((addr + 4 * nregs) - 1) >> 5) - 2)
399 1.1 christos {
400 1.1 christos PENALIZE1 (movemaddr_stall_count);
401 1.1 christos PENALIZE1 (movemaddr_stall_count);
402 1.1 christos }
403 1.1 christos
404 1.1 christos model_data->modf_regs |= ((1 << nregs) - 1);
405 1.1 christos model_data->movem_dest_regs |= ((1 << nregs) - 1);
406 1.1 christos return 0;
407 1.1 christos }
408 1.1 christos
409 1.1 christos
410 1.1 christos /* Model function for u-branch unit.
411 1.1 christos FIXME: newpc and cc are always wrong. */
412 1.1 christos
413 1.1 christos int
414 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,_u_branch)) (SIM_CPU *current_cpu,
415 1.1 christos const IDESC *idesc,
416 1.1 christos int unit_num, int referenced)
417 1.1 christos {
418 1.1 christos CRIS_MISC_PROFILE *profp = CPU_CRIS_MISC_PROFILE (current_cpu);
419 1.1 christos USI pc = profp->old_pc;
420 1.1 christos MODEL_CRISV32_DATA *model_data
421 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
422 1.1 christos int taken = profp->branch_taken;
423 1.1 christos int branch_index = (pc & (N_CRISV32_BRANCH_PREDICTORS - 1)) >> 1;
424 1.1 christos int pred_taken = (profp->branch_predictors[branch_index] & 2) != 0;
425 1.1 christos
426 1.1 christos if (taken != pred_taken)
427 1.1 christos {
428 1.1 christos PENALIZE1 (branch_stall_count);
429 1.1 christos PENALIZE1 (branch_stall_count);
430 1.1 christos }
431 1.1 christos
432 1.1 christos if (taken)
433 1.1 christos {
434 1.1 christos if (profp->branch_predictors[branch_index] < 3)
435 1.1 christos profp->branch_predictors[branch_index]++;
436 1.1 christos
437 1.1 christos return MY (XCONCAT3 (f_model_crisv,BASENUM,_u_jump))
438 1.1 christos (current_cpu, idesc, unit_num, referenced, -1);
439 1.1 christos }
440 1.1 christos
441 1.1 christos if (profp->branch_predictors[branch_index] != 0)
442 1.1 christos profp->branch_predictors[branch_index]--;
443 1.1 christos
444 1.1 christos return 0;
445 1.1 christos }
446 1.1 christos
447 1.1 christos /* Model function for u-jump-r unit. */
448 1.1 christos
449 1.1 christos int
450 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
451 1.1 christos _u_jump_r)) (SIM_CPU *current_cpu,
452 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
453 1.1 christos int unit_num ATTRIBUTE_UNUSED,
454 1.1 christos int referenced ATTRIBUTE_UNUSED,
455 1.1 christos int regno)
456 1.1 christos {
457 1.1 christos MODEL_CRISV32_DATA *model_data
458 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
459 1.1 christos
460 1.1 christos if (regno == -1)
461 1.1 christos abort ();
462 1.1 christos
463 1.1 christos /* For jump-to-register, the register must not have been modified the
464 1.1 christos last two cycles. Penalty: two cycles from the modifying insn. */
465 1.1 christos if ((1 << regno) & model_data->prev_modf_regs)
466 1.1 christos {
467 1.1 christos PENALIZE1 (jumpsrc_stall_count);
468 1.1 christos PENALIZE1 (jumpsrc_stall_count);
469 1.1 christos }
470 1.1 christos else if ((1 << regno) & model_data->prev_prev_modf_regs)
471 1.1 christos PENALIZE1 (jumpsrc_stall_count);
472 1.1 christos
473 1.1 christos return 0;
474 1.1 christos }
475 1.1 christos
476 1.1 christos /* Model function for u-jump-sr unit. */
477 1.1 christos
478 1.1 christos int
479 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,_u_jump_sr)) (SIM_CPU *current_cpu,
480 1.1 christos const IDESC *idesc,
481 1.1 christos int unit_num, int referenced,
482 1.1 christos int sr_regno)
483 1.1 christos {
484 1.1 christos int regno;
485 1.1 christos
486 1.1 christos MODEL_CRISV32_DATA *model_data
487 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
488 1.1 christos
489 1.1 christos if (sr_regno == -1)
490 1.1 christos abort ();
491 1.1 christos
492 1.1 christos regno = sr_regno + 16;
493 1.1 christos
494 1.1 christos /* For jump-to-register, the register must not have been modified the
495 1.1 christos last two cycles. Penalty: two cycles from the modifying insn. */
496 1.1 christos if ((1 << regno) & model_data->prev_modf_regs)
497 1.1 christos {
498 1.1 christos PENALIZE1 (jumpsrc_stall_count);
499 1.1 christos PENALIZE1 (jumpsrc_stall_count);
500 1.1 christos }
501 1.1 christos else if ((1 << regno) & model_data->prev_prev_modf_regs)
502 1.1 christos PENALIZE1 (jumpsrc_stall_count);
503 1.1 christos
504 1.1 christos return
505 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,_u_jump)) (current_cpu, idesc,
506 1.1 christos unit_num, referenced, -1);
507 1.1 christos }
508 1.1 christos
509 1.1 christos /* Model function for u-jump unit. */
510 1.1 christos
511 1.1 christos int
512 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
513 1.1 christos _u_jump)) (SIM_CPU *current_cpu,
514 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
515 1.1 christos int unit_num ATTRIBUTE_UNUSED,
516 1.1 christos int referenced ATTRIBUTE_UNUSED,
517 1.1 christos int out_sr_regno)
518 1.1 christos {
519 1.1 christos MODEL_CRISV32_DATA *model_data
520 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
521 1.1 christos
522 1.1 christos /* Mark that we made a jump. */
523 1.1 christos model_data->modf_regs
524 1.1 christos |= (CRIS_MODF_JUMP_MASK
525 1.1 christos | (out_sr_regno == -1 || out_sr_regno == CRIS_BZ_REGNO
526 1.1 christos ? 0 : (1 << (out_sr_regno + 16))));
527 1.1 christos return 0;
528 1.1 christos }
529 1.1 christos
530 1.1 christos /* Model function for u-multiply unit. */
531 1.1 christos
532 1.1 christos int
533 1.1 christos MY (XCONCAT3 (f_model_crisv,BASENUM,
534 1.1 christos _u_multiply)) (SIM_CPU *current_cpu,
535 1.1 christos const IDESC *idesc ATTRIBUTE_UNUSED,
536 1.1 christos int unit_num ATTRIBUTE_UNUSED,
537 1.1 christos int referenced ATTRIBUTE_UNUSED,
538 1.1 christos int srcreg, int destreg)
539 1.1 christos {
540 1.1 christos MODEL_CRISV32_DATA *model_data
541 1.1 christos = (MODEL_CRISV32_DATA *) CPU_MODEL_DATA (current_cpu);
542 1.1 christos
543 1.1 christos /* Sanity-check for cases that should never happen. */
544 1.1 christos if (srcreg == -1 || destreg == -1)
545 1.1 christos abort ();
546 1.1 christos
547 1.1 christos /* This takes extra cycles when one of the inputs has been modified
548 1.1 christos through other than autoincrement in the previous cycle. Penalty:
549 1.1 christos one cycle. */
550 1.1 christos if (((1 << srcreg) | (1 << destreg)) & model_data->prev_modf_regs)
551 1.1 christos PENALIZE1 (mulsrc_stall_count);
552 1.1 christos
553 1.1 christos /* We modified the multiplication destination (marked in u-exec) and
554 1.1 christos the MOF register. */
555 1.1 christos model_data->modf_regs |= (1 << CRIS_MOF_REGNO);
556 1.1 christos return 0;
557 1.1 christos }
558 1.1 christos
559 1.1 christos #endif /* WITH_PROFILE_MODEL_P */
560 1.1 christos
561 1.1 christos int
562 1.1 christos MY (deliver_interrupt) (SIM_CPU *current_cpu,
563 1.1 christos enum cris_interrupt_type type,
564 1.1 christos unsigned int vec)
565 1.1 christos {
566 1.1 christos unsigned32 old_ccs, shifted_ccs, new_ccs;
567 1.1 christos unsigned char entryaddr_le[4];
568 1.1 christos int was_user;
569 1.1 christos SIM_DESC sd = CPU_STATE (current_cpu);
570 1.1 christos unsigned32 entryaddr;
571 1.1 christos
572 1.1 christos /* We haven't implemented other interrupt-types yet. */
573 1.1 christos if (type != CRIS_INT_INT)
574 1.1 christos abort ();
575 1.1 christos
576 1.1 christos /* We're called outside of branch delay slots etc, so we don't check
577 1.1 christos for that. */
578 1.1 christos if (!GET_H_IBIT_V32 ())
579 1.1 christos return 0;
580 1.1 christos
581 1.1 christos old_ccs = GET_H_SR_V32 (H_SR_CCS);
582 1.1 christos shifted_ccs = (old_ccs << 10) & ((1 << 30) - 1);
583 1.1 christos
584 1.1 christos /* The M bit is handled by code below and the M bit setter function, but
585 1.1 christos we need to preserve the Q bit. */
586 1.1 christos new_ccs = shifted_ccs | (old_ccs & (unsigned32) 0x80000000UL);
587 1.1 christos was_user = GET_H_UBIT_V32 ();
588 1.1 christos
589 1.1 christos /* We need to force kernel mode since the setter method doesn't allow
590 1.1 christos it. Then we can use setter methods at will, since they then
591 1.1 christos recognize that we're in kernel mode. */
592 1.1 christos CPU (h_ubit_v32) = 0;
593 1.1 christos
594 1.1 christos SET_H_SR (H_SR_CCS, new_ccs);
595 1.1 christos
596 1.1 christos if (was_user)
597 1.1 christos {
598 1.1 christos /* These methods require that user mode is unset. */
599 1.1 christos SET_H_SR (H_SR_USP, GET_H_GR (H_GR_SP));
600 1.1 christos SET_H_GR (H_GR_SP, GET_H_KERNEL_SP ());
601 1.1 christos }
602 1.1 christos
603 1.1 christos /* ERP setting is simplified by not taking interrupts in delay-slots
604 1.1 christos or when halting. */
605 1.1 christos /* For all other exceptions than guru and NMI, store the return
606 1.1 christos address in ERP and set EXS and EXD here. */
607 1.1 christos SET_H_SR (H_SR_ERP, GET_H_PC ());
608 1.1 christos
609 1.1 christos /* Simplified by not having exception types (fault indications). */
610 1.1 christos SET_H_SR_V32 (H_SR_EXS, (vec * 256));
611 1.1 christos SET_H_SR_V32 (H_SR_EDA, 0);
612 1.1 christos
613 1.1 christos if (sim_core_read_buffer (sd,
614 1.1 christos current_cpu,
615 1.1 christos read_map, entryaddr_le,
616 1.1 christos GET_H_SR (H_SR_EBP) + vec * 4, 4) == 0)
617 1.1 christos {
618 1.1 christos /* Nothing to do actually; either abort or send a signal. */
619 1.1 christos sim_core_signal (sd, current_cpu, CIA_GET (current_cpu), 0, 4,
620 1.1 christos GET_H_SR (H_SR_EBP) + vec * 4,
621 1.1 christos read_transfer, sim_core_unmapped_signal);
622 1.1 christos return 0;
623 1.1 christos }
624 1.1 christos
625 1.1 christos entryaddr = bfd_getl32 (entryaddr_le);
626 1.1 christos SET_H_PC (entryaddr);
627 1.1 christos
628 1.1 christos return 1;
629 1.1 christos }
630