Switch the license of all files explicitly copyright the FSF
[deliverable/binutils-gdb.git] / sim / frv / frv.c
CommitLineData
b34f6357 1/* frv simulator support code
6aba47ca
DJ
2 Copyright (C) 1998, 1999, 2000, 2001, 2003, 2004, 2007
3 Free Software Foundation, Inc.
b34f6357
DB
4 Contributed by Red Hat.
5
6This file is part of the GNU simulators.
7
8This program is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
4744ac1b
JB
10the Free Software Foundation; either version 3 of the License, or
11(at your option) any later version.
b34f6357
DB
12
13This program is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
4744ac1b
JB
18You should have received a copy of the GNU General Public License
19along with this program. If not, see <http://www.gnu.org/licenses/>. */
b34f6357
DB
20
21#define WANT_CPU
22#define WANT_CPU_FRVBF
23
24#include "sim-main.h"
25#include "cgen-mem.h"
26#include "cgen-ops.h"
27#include "cgen-engine.h"
28#include "cgen-par.h"
29#include "bfd.h"
d74c4203 30#include "gdb/sim-frv.h"
b34f6357
DB
31#include <math.h>
32
33/* Maintain a flag in order to know when to write the address of the next
34 VLIW instruction into the LR register. Used by JMPL. JMPIL, and CALL
35 insns. */
36int frvbf_write_next_vliw_addr_to_LR;
37
38/* The contents of BUF are in target byte order. */
39int
40frvbf_fetch_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len)
41{
d74c4203
KB
42 if (SIM_FRV_GR0_REGNUM <= rn && rn <= SIM_FRV_GR63_REGNUM)
43 {
44 int hi_available, lo_available;
45 int grn = rn - SIM_FRV_GR0_REGNUM;
46
47 frv_gr_registers_available (current_cpu, &hi_available, &lo_available);
48
49 if ((grn < 32 && !lo_available) || (grn >= 32 && !hi_available))
50 return 0;
51 else
52 SETTSI (buf, GET_H_GR (grn));
53 }
54 else if (SIM_FRV_FR0_REGNUM <= rn && rn <= SIM_FRV_FR63_REGNUM)
55 {
56 int hi_available, lo_available;
57 int frn = rn - SIM_FRV_FR0_REGNUM;
58
59 frv_fr_registers_available (current_cpu, &hi_available, &lo_available);
60
61 if ((frn < 32 && !lo_available) || (frn >= 32 && !hi_available))
62 return 0;
63 else
64 SETTSI (buf, GET_H_FR (frn));
65 }
66 else if (rn == SIM_FRV_PC_REGNUM)
b34f6357 67 SETTSI (buf, GET_H_PC ());
d74c4203 68 else if (SIM_FRV_SPR0_REGNUM <= rn && rn <= SIM_FRV_SPR4095_REGNUM)
9a29f3ca
DB
69 {
70 /* Make sure the register is implemented. */
71 FRV_REGISTER_CONTROL *control = CPU_REGISTER_CONTROL (current_cpu);
d74c4203 72 int spr = rn - SIM_FRV_SPR0_REGNUM;
9a29f3ca
DB
73 if (! control->spr[spr].implemented)
74 return 0;
75 SETTSI (buf, GET_H_SPR (spr));
76 }
b34f6357 77 else
9a29f3ca
DB
78 {
79 SETTSI (buf, 0xdeadbeef);
80 return 0;
81 }
b34f6357 82
9a29f3ca 83 return len;
b34f6357
DB
84}
85
86/* The contents of BUF are in target byte order. */
87
88int
89frvbf_store_register (SIM_CPU *current_cpu, int rn, unsigned char *buf, int len)
90{
d74c4203
KB
91 if (SIM_FRV_GR0_REGNUM <= rn && rn <= SIM_FRV_GR63_REGNUM)
92 {
93 int hi_available, lo_available;
94 int grn = rn - SIM_FRV_GR0_REGNUM;
95
96 frv_gr_registers_available (current_cpu, &hi_available, &lo_available);
97
98 if ((grn < 32 && !lo_available) || (grn >= 32 && !hi_available))
99 return 0;
100 else
101 SET_H_GR (grn, GETTSI (buf));
102 }
103 else if (SIM_FRV_FR0_REGNUM <= rn && rn <= SIM_FRV_FR63_REGNUM)
104 {
105 int hi_available, lo_available;
106 int frn = rn - SIM_FRV_FR0_REGNUM;
107
108 frv_fr_registers_available (current_cpu, &hi_available, &lo_available);
109
110 if ((frn < 32 && !lo_available) || (frn >= 32 && !hi_available))
111 return 0;
112 else
113 SET_H_FR (frn, GETTSI (buf));
114 }
115 else if (rn == SIM_FRV_PC_REGNUM)
b34f6357 116 SET_H_PC (GETTSI (buf));
d74c4203 117 else if (SIM_FRV_SPR0_REGNUM <= rn && rn <= SIM_FRV_SPR4095_REGNUM)
9a29f3ca
DB
118 {
119 /* Make sure the register is implemented. */
120 FRV_REGISTER_CONTROL *control = CPU_REGISTER_CONTROL (current_cpu);
d74c4203 121 int spr = rn - SIM_FRV_SPR0_REGNUM;
9a29f3ca
DB
122 if (! control->spr[spr].implemented)
123 return 0;
124 SET_H_SPR (spr, GETTSI (buf));
125 }
126 else
127 return 0;
b34f6357 128
9a29f3ca 129 return len;
b34f6357
DB
130}
131\f
132/* Cover fns to access the general registers. */
133USI
134frvbf_h_gr_get_handler (SIM_CPU *current_cpu, UINT gr)
135{
136 frv_check_gr_access (current_cpu, gr);
137 return CPU (h_gr[gr]);
138}
139
140void
141frvbf_h_gr_set_handler (SIM_CPU *current_cpu, UINT gr, USI newval)
142{
143 frv_check_gr_access (current_cpu, gr);
144
145 if (gr == 0)
146 return; /* Storing into gr0 has no effect. */
147
148 CPU (h_gr[gr]) = newval;
149}
150\f
151/* Cover fns to access the floating point registers. */
152SF
153frvbf_h_fr_get_handler (SIM_CPU *current_cpu, UINT fr)
154{
155 frv_check_fr_access (current_cpu, fr);
156 return CPU (h_fr[fr]);
157}
158
159void
160frvbf_h_fr_set_handler (SIM_CPU *current_cpu, UINT fr, SF newval)
161{
162 frv_check_fr_access (current_cpu, fr);
163 CPU (h_fr[fr]) = newval;
164}
165\f
166/* Cover fns to access the general registers as double words. */
167static UINT
168check_register_alignment (SIM_CPU *current_cpu, UINT reg, int align_mask)
169{
170 if (reg & align_mask)
171 {
172 SIM_DESC sd = CPU_STATE (current_cpu);
173 switch (STATE_ARCHITECTURE (sd)->mach)
174 {
676a64f4
RS
175 /* Note: there is a discrepancy between V2.2 of the FR400
176 instruction manual and the various FR4xx LSI specs.
177 The former claims that unaligned registers cause a
178 register_exception while the latter say it's an
179 illegal_instruction. The LSI specs appear to be
180 correct; in fact, the FR4xx series is not documented
181 as having a register_exception. */
b34f6357 182 case bfd_mach_fr400:
676a64f4 183 case bfd_mach_fr450:
e930b1f5 184 case bfd_mach_fr550:
b34f6357
DB
185 frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
186 break;
187 case bfd_mach_frvtomcat:
188 case bfd_mach_fr500:
189 case bfd_mach_frv:
190 frv_queue_register_exception_interrupt (current_cpu,
191 FRV_REC_UNALIGNED);
192 break;
193 default:
194 break;
195 }
196
197 reg &= ~align_mask;
198 }
199
200 return reg;
201}
202
203static UINT
204check_fr_register_alignment (SIM_CPU *current_cpu, UINT reg, int align_mask)
205{
206 if (reg & align_mask)
207 {
208 SIM_DESC sd = CPU_STATE (current_cpu);
209 switch (STATE_ARCHITECTURE (sd)->mach)
210 {
676a64f4 211 /* See comment in check_register_alignment(). */
b34f6357 212 case bfd_mach_fr400:
676a64f4 213 case bfd_mach_fr450:
e930b1f5 214 case bfd_mach_fr550:
b34f6357
DB
215 frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
216 break;
217 case bfd_mach_frvtomcat:
218 case bfd_mach_fr500:
219 case bfd_mach_frv:
220 {
221 struct frv_fp_exception_info fp_info = {
222 FSR_NO_EXCEPTION, FTT_INVALID_FR
223 };
224 frv_queue_fp_exception_interrupt (current_cpu, & fp_info);
225 }
226 break;
227 default:
228 break;
229 }
230
231 reg &= ~align_mask;
232 }
233
234 return reg;
235}
236
237static UINT
238check_memory_alignment (SIM_CPU *current_cpu, SI address, int align_mask)
239{
240 if (address & align_mask)
241 {
242 SIM_DESC sd = CPU_STATE (current_cpu);
243 switch (STATE_ARCHITECTURE (sd)->mach)
244 {
676a64f4 245 /* See comment in check_register_alignment(). */
b34f6357 246 case bfd_mach_fr400:
676a64f4 247 case bfd_mach_fr450:
b34f6357
DB
248 frv_queue_data_access_error_interrupt (current_cpu, address);
249 break;
250 case bfd_mach_frvtomcat:
251 case bfd_mach_fr500:
252 case bfd_mach_frv:
253 frv_queue_mem_address_not_aligned_interrupt (current_cpu, address);
254 break;
255 default:
256 break;
257 }
258
259 address &= ~align_mask;
260 }
261
262 return address;
263}
264
265DI
266frvbf_h_gr_double_get_handler (SIM_CPU *current_cpu, UINT gr)
267{
268 DI value;
269
270 if (gr == 0)
271 return 0; /* gr0 is always 0. */
272
273 /* Check the register alignment. */
274 gr = check_register_alignment (current_cpu, gr, 1);
275
276 value = GET_H_GR (gr);
277 value <<= 32;
278 value |= (USI) GET_H_GR (gr + 1);
279 return value;
280}
281
282void
283frvbf_h_gr_double_set_handler (SIM_CPU *current_cpu, UINT gr, DI newval)
284{
285 if (gr == 0)
286 return; /* Storing into gr0 has no effect. */
287
288 /* Check the register alignment. */
289 gr = check_register_alignment (current_cpu, gr, 1);
290
291 SET_H_GR (gr , (newval >> 32) & 0xffffffff);
292 SET_H_GR (gr + 1, (newval ) & 0xffffffff);
293}
294\f
295/* Cover fns to access the floating point register as double words. */
296DF
297frvbf_h_fr_double_get_handler (SIM_CPU *current_cpu, UINT fr)
298{
299 union {
300 SF as_sf[2];
301 DF as_df;
302 } value;
303
304 /* Check the register alignment. */
305 fr = check_fr_register_alignment (current_cpu, fr, 1);
306
307 if (CURRENT_HOST_BYTE_ORDER == LITTLE_ENDIAN)
308 {
309 value.as_sf[1] = GET_H_FR (fr);
310 value.as_sf[0] = GET_H_FR (fr + 1);
311 }
312 else
313 {
314 value.as_sf[0] = GET_H_FR (fr);
315 value.as_sf[1] = GET_H_FR (fr + 1);
316 }
317
318 return value.as_df;
319}
320
321void
322frvbf_h_fr_double_set_handler (SIM_CPU *current_cpu, UINT fr, DF newval)
323{
324 union {
325 SF as_sf[2];
326 DF as_df;
327 } value;
328
329 /* Check the register alignment. */
330 fr = check_fr_register_alignment (current_cpu, fr, 1);
331
332 value.as_df = newval;
333 if (CURRENT_HOST_BYTE_ORDER == LITTLE_ENDIAN)
334 {
335 SET_H_FR (fr , value.as_sf[1]);
336 SET_H_FR (fr + 1, value.as_sf[0]);
337 }
338 else
339 {
340 SET_H_FR (fr , value.as_sf[0]);
341 SET_H_FR (fr + 1, value.as_sf[1]);
342 }
343}
344\f
345/* Cover fns to access the floating point register as integer words. */
346USI
347frvbf_h_fr_int_get_handler (SIM_CPU *current_cpu, UINT fr)
348{
349 union {
350 SF as_sf;
351 USI as_usi;
352 } value;
353
354 value.as_sf = GET_H_FR (fr);
355 return value.as_usi;
356}
357
358void
359frvbf_h_fr_int_set_handler (SIM_CPU *current_cpu, UINT fr, USI newval)
360{
361 union {
362 SF as_sf;
363 USI as_usi;
364 } value;
365
366 value.as_usi = newval;
367 SET_H_FR (fr, value.as_sf);
368}
369\f
370/* Cover fns to access the coprocessor registers as double words. */
371DI
372frvbf_h_cpr_double_get_handler (SIM_CPU *current_cpu, UINT cpr)
373{
374 DI value;
375
376 /* Check the register alignment. */
377 cpr = check_register_alignment (current_cpu, cpr, 1);
378
379 value = GET_H_CPR (cpr);
380 value <<= 32;
381 value |= (USI) GET_H_CPR (cpr + 1);
382 return value;
383}
384
385void
386frvbf_h_cpr_double_set_handler (SIM_CPU *current_cpu, UINT cpr, DI newval)
387{
388 /* Check the register alignment. */
389 cpr = check_register_alignment (current_cpu, cpr, 1);
390
391 SET_H_CPR (cpr , (newval >> 32) & 0xffffffff);
392 SET_H_CPR (cpr + 1, (newval ) & 0xffffffff);
393}
394\f
395/* Cover fns to write registers as quad words. */
396void
397frvbf_h_gr_quad_set_handler (SIM_CPU *current_cpu, UINT gr, SI *newval)
398{
399 if (gr == 0)
400 return; /* Storing into gr0 has no effect. */
401
402 /* Check the register alignment. */
403 gr = check_register_alignment (current_cpu, gr, 3);
404
405 SET_H_GR (gr , newval[0]);
406 SET_H_GR (gr + 1, newval[1]);
407 SET_H_GR (gr + 2, newval[2]);
408 SET_H_GR (gr + 3, newval[3]);
409}
410
411void
412frvbf_h_fr_quad_set_handler (SIM_CPU *current_cpu, UINT fr, SI *newval)
413{
414 /* Check the register alignment. */
415 fr = check_fr_register_alignment (current_cpu, fr, 3);
416
417 SET_H_FR (fr , newval[0]);
418 SET_H_FR (fr + 1, newval[1]);
419 SET_H_FR (fr + 2, newval[2]);
420 SET_H_FR (fr + 3, newval[3]);
421}
422
423void
424frvbf_h_cpr_quad_set_handler (SIM_CPU *current_cpu, UINT cpr, SI *newval)
425{
426 /* Check the register alignment. */
427 cpr = check_register_alignment (current_cpu, cpr, 3);
428
429 SET_H_CPR (cpr , newval[0]);
430 SET_H_CPR (cpr + 1, newval[1]);
431 SET_H_CPR (cpr + 2, newval[2]);
432 SET_H_CPR (cpr + 3, newval[3]);
433}
434\f
435/* Cover fns to access the special purpose registers. */
436USI
437frvbf_h_spr_get_handler (SIM_CPU *current_cpu, UINT spr)
438{
439 /* Check access restrictions. */
440 frv_check_spr_read_access (current_cpu, spr);
441
442 switch (spr)
443 {
444 case H_SPR_PSR:
445 return spr_psr_get_handler (current_cpu);
446 case H_SPR_TBR:
447 return spr_tbr_get_handler (current_cpu);
448 case H_SPR_BPSR:
449 return spr_bpsr_get_handler (current_cpu);
450 case H_SPR_CCR:
451 return spr_ccr_get_handler (current_cpu);
452 case H_SPR_CCCR:
453 return spr_cccr_get_handler (current_cpu);
454 case H_SPR_SR0:
455 case H_SPR_SR1:
456 case H_SPR_SR2:
457 case H_SPR_SR3:
458 return spr_sr_get_handler (current_cpu, spr);
459 break;
460 default:
461 return CPU (h_spr[spr]);
462 }
463 return 0;
464}
465
466void
467frvbf_h_spr_set_handler (SIM_CPU *current_cpu, UINT spr, USI newval)
468{
469 FRV_REGISTER_CONTROL *control;
470 USI mask;
471 USI oldval;
472
473 /* Check access restrictions. */
474 frv_check_spr_write_access (current_cpu, spr);
475
476 /* Only set those fields which are writeable. */
477 control = CPU_REGISTER_CONTROL (current_cpu);
478 mask = control->spr[spr].read_only_mask;
479 oldval = GET_H_SPR (spr);
480
481 newval = (newval & ~mask) | (oldval & mask);
482
483 /* Some registers are represented by individual components which are
484 referenced more often than the register itself. */
485 switch (spr)
486 {
487 case H_SPR_PSR:
488 spr_psr_set_handler (current_cpu, newval);
489 break;
490 case H_SPR_TBR:
491 spr_tbr_set_handler (current_cpu, newval);
492 break;
493 case H_SPR_BPSR:
494 spr_bpsr_set_handler (current_cpu, newval);
495 break;
496 case H_SPR_CCR:
497 spr_ccr_set_handler (current_cpu, newval);
498 break;
499 case H_SPR_CCCR:
500 spr_cccr_set_handler (current_cpu, newval);
501 break;
502 case H_SPR_SR0:
503 case H_SPR_SR1:
504 case H_SPR_SR2:
505 case H_SPR_SR3:
506 spr_sr_set_handler (current_cpu, spr, newval);
507 break;
e930b1f5
DB
508 case H_SPR_IHSR8:
509 frv_cache_reconfigure (current_cpu, CPU_INSN_CACHE (current_cpu));
510 break;
b34f6357
DB
511 default:
512 CPU (h_spr[spr]) = newval;
513 break;
514 }
515}
516\f
517/* Cover fns to access the gr_hi and gr_lo registers. */
518UHI
519frvbf_h_gr_hi_get_handler (SIM_CPU *current_cpu, UINT gr)
520{
521 return (GET_H_GR(gr) >> 16) & 0xffff;
522}
523
524void
525frvbf_h_gr_hi_set_handler (SIM_CPU *current_cpu, UINT gr, UHI newval)
526{
527 USI value = (GET_H_GR (gr) & 0xffff) | (newval << 16);
528 SET_H_GR (gr, value);
529}
530
531UHI
532frvbf_h_gr_lo_get_handler (SIM_CPU *current_cpu, UINT gr)
533{
534 return GET_H_GR(gr) & 0xffff;
535}
536
537void
538frvbf_h_gr_lo_set_handler (SIM_CPU *current_cpu, UINT gr, UHI newval)
539{
540 USI value = (GET_H_GR (gr) & 0xffff0000) | (newval & 0xffff);
541 SET_H_GR (gr, value);
542}
543\f
544/* Cover fns to access the tbr bits. */
545USI
546spr_tbr_get_handler (SIM_CPU *current_cpu)
547{
548 int tbr = ((GET_H_TBR_TBA () & 0xfffff) << 12) |
549 ((GET_H_TBR_TT () & 0xff) << 4);
550
551 return tbr;
552}
553
554void
555spr_tbr_set_handler (SIM_CPU *current_cpu, USI newval)
556{
557 int tbr = newval;
558
559 SET_H_TBR_TBA ((tbr >> 12) & 0xfffff) ;
560 SET_H_TBR_TT ((tbr >> 4) & 0xff) ;
561}
562\f
563/* Cover fns to access the bpsr bits. */
564USI
565spr_bpsr_get_handler (SIM_CPU *current_cpu)
566{
567 int bpsr = ((GET_H_BPSR_BS () & 0x1) << 12) |
568 ((GET_H_BPSR_BET () & 0x1) );
569
570 return bpsr;
571}
572
573void
574spr_bpsr_set_handler (SIM_CPU *current_cpu, USI newval)
575{
576 int bpsr = newval;
577
578 SET_H_BPSR_BS ((bpsr >> 12) & 1);
579 SET_H_BPSR_BET ((bpsr ) & 1);
580}
581\f
582/* Cover fns to access the psr bits. */
583USI
584spr_psr_get_handler (SIM_CPU *current_cpu)
585{
586 int psr = ((GET_H_PSR_IMPLE () & 0xf) << 28) |
587 ((GET_H_PSR_VER () & 0xf) << 24) |
588 ((GET_H_PSR_ICE () & 0x1) << 16) |
589 ((GET_H_PSR_NEM () & 0x1) << 14) |
590 ((GET_H_PSR_CM () & 0x1) << 13) |
591 ((GET_H_PSR_BE () & 0x1) << 12) |
592 ((GET_H_PSR_ESR () & 0x1) << 11) |
593 ((GET_H_PSR_EF () & 0x1) << 8) |
594 ((GET_H_PSR_EM () & 0x1) << 7) |
595 ((GET_H_PSR_PIL () & 0xf) << 3) |
596 ((GET_H_PSR_S () & 0x1) << 2) |
597 ((GET_H_PSR_PS () & 0x1) << 1) |
598 ((GET_H_PSR_ET () & 0x1) );
599
600 return psr;
601}
602
603void
604spr_psr_set_handler (SIM_CPU *current_cpu, USI newval)
605{
606 /* The handler for PSR.S references the value of PSR.ESR, so set PSR.S
607 first. */
608 SET_H_PSR_S ((newval >> 2) & 1);
609
610 SET_H_PSR_IMPLE ((newval >> 28) & 0xf);
611 SET_H_PSR_VER ((newval >> 24) & 0xf);
612 SET_H_PSR_ICE ((newval >> 16) & 1);
613 SET_H_PSR_NEM ((newval >> 14) & 1);
614 SET_H_PSR_CM ((newval >> 13) & 1);
615 SET_H_PSR_BE ((newval >> 12) & 1);
616 SET_H_PSR_ESR ((newval >> 11) & 1);
617 SET_H_PSR_EF ((newval >> 8) & 1);
618 SET_H_PSR_EM ((newval >> 7) & 1);
619 SET_H_PSR_PIL ((newval >> 3) & 0xf);
620 SET_H_PSR_PS ((newval >> 1) & 1);
621 SET_H_PSR_ET ((newval ) & 1);
622}
623
624void
625frvbf_h_psr_s_set_handler (SIM_CPU *current_cpu, BI newval)
626{
627 /* If switching from user to supervisor mode, or vice-versa, then switch
628 the supervisor/user context. */
629 int psr_s = GET_H_PSR_S ();
630 if (psr_s != (newval & 1))
631 {
632 frvbf_switch_supervisor_user_context (current_cpu);
633 CPU (h_psr_s) = newval & 1;
634 }
635}
636\f
637/* Cover fns to access the ccr bits. */
638USI
639spr_ccr_get_handler (SIM_CPU *current_cpu)
640{
641 int ccr = ((GET_H_ICCR (H_ICCR_ICC3) & 0xf) << 28) |
642 ((GET_H_ICCR (H_ICCR_ICC2) & 0xf) << 24) |
643 ((GET_H_ICCR (H_ICCR_ICC1) & 0xf) << 20) |
644 ((GET_H_ICCR (H_ICCR_ICC0) & 0xf) << 16) |
645 ((GET_H_FCCR (H_FCCR_FCC3) & 0xf) << 12) |
646 ((GET_H_FCCR (H_FCCR_FCC2) & 0xf) << 8) |
647 ((GET_H_FCCR (H_FCCR_FCC1) & 0xf) << 4) |
648 ((GET_H_FCCR (H_FCCR_FCC0) & 0xf) );
649
650 return ccr;
651}
652
653void
654spr_ccr_set_handler (SIM_CPU *current_cpu, USI newval)
655{
656 int ccr = newval;
657
658 SET_H_ICCR (H_ICCR_ICC3, (newval >> 28) & 0xf);
659 SET_H_ICCR (H_ICCR_ICC2, (newval >> 24) & 0xf);
660 SET_H_ICCR (H_ICCR_ICC1, (newval >> 20) & 0xf);
661 SET_H_ICCR (H_ICCR_ICC0, (newval >> 16) & 0xf);
662 SET_H_FCCR (H_FCCR_FCC3, (newval >> 12) & 0xf);
663 SET_H_FCCR (H_FCCR_FCC2, (newval >> 8) & 0xf);
664 SET_H_FCCR (H_FCCR_FCC1, (newval >> 4) & 0xf);
665 SET_H_FCCR (H_FCCR_FCC0, (newval ) & 0xf);
666}
667\f
668QI
669frvbf_set_icc_for_shift_right (
670 SIM_CPU *current_cpu, SI value, SI shift, QI icc
671)
672{
673 /* Set the C flag of the given icc to the logical OR of the bits shifted
674 out. */
675 int mask = (1 << shift) - 1;
676 if ((value & mask) != 0)
677 return icc | 0x1;
678
679 return icc & 0xe;
680}
681
682QI
683frvbf_set_icc_for_shift_left (
684 SIM_CPU *current_cpu, SI value, SI shift, QI icc
685)
686{
687 /* Set the V flag of the given icc to the logical OR of the bits shifted
688 out. */
689 int mask = ((1 << shift) - 1) << (32 - shift);
690 if ((value & mask) != 0)
691 return icc | 0x2;
692
693 return icc & 0xd;
694}
695\f
696/* Cover fns to access the cccr bits. */
697USI
698spr_cccr_get_handler (SIM_CPU *current_cpu)
699{
700 int cccr = ((GET_H_CCCR (H_CCCR_CC7) & 0x3) << 14) |
701 ((GET_H_CCCR (H_CCCR_CC6) & 0x3) << 12) |
702 ((GET_H_CCCR (H_CCCR_CC5) & 0x3) << 10) |
703 ((GET_H_CCCR (H_CCCR_CC4) & 0x3) << 8) |
704 ((GET_H_CCCR (H_CCCR_CC3) & 0x3) << 6) |
705 ((GET_H_CCCR (H_CCCR_CC2) & 0x3) << 4) |
706 ((GET_H_CCCR (H_CCCR_CC1) & 0x3) << 2) |
707 ((GET_H_CCCR (H_CCCR_CC0) & 0x3) );
708
709 return cccr;
710}
711
712void
713spr_cccr_set_handler (SIM_CPU *current_cpu, USI newval)
714{
715 int cccr = newval;
716
717 SET_H_CCCR (H_CCCR_CC7, (newval >> 14) & 0x3);
718 SET_H_CCCR (H_CCCR_CC6, (newval >> 12) & 0x3);
719 SET_H_CCCR (H_CCCR_CC5, (newval >> 10) & 0x3);
720 SET_H_CCCR (H_CCCR_CC4, (newval >> 8) & 0x3);
721 SET_H_CCCR (H_CCCR_CC3, (newval >> 6) & 0x3);
722 SET_H_CCCR (H_CCCR_CC2, (newval >> 4) & 0x3);
723 SET_H_CCCR (H_CCCR_CC1, (newval >> 2) & 0x3);
724 SET_H_CCCR (H_CCCR_CC0, (newval ) & 0x3);
725}
726\f
727/* Cover fns to access the sr bits. */
728USI
729spr_sr_get_handler (SIM_CPU *current_cpu, UINT spr)
730{
731 /* If PSR.ESR is not set, then SR0-3 map onto SGR4-7 which will be GR4-7,
732 otherwise the correct mapping of USG4-7 or SGR4-7 will be in SR0-3. */
733 int psr_esr = GET_H_PSR_ESR ();
734 if (! psr_esr)
735 return GET_H_GR (4 + (spr - H_SPR_SR0));
736
737 return CPU (h_spr[spr]);
738}
739
740void
741spr_sr_set_handler (SIM_CPU *current_cpu, UINT spr, USI newval)
742{
743 /* If PSR.ESR is not set, then SR0-3 map onto SGR4-7 which will be GR4-7,
744 otherwise the correct mapping of USG4-7 or SGR4-7 will be in SR0-3. */
745 int psr_esr = GET_H_PSR_ESR ();
746 if (! psr_esr)
747 SET_H_GR (4 + (spr - H_SPR_SR0), newval);
748 else
749 CPU (h_spr[spr]) = newval;
750}
751\f
752/* Switch SR0-SR4 with GR4-GR7 if PSR.ESR is set. */
753void
754frvbf_switch_supervisor_user_context (SIM_CPU *current_cpu)
755{
756 if (GET_H_PSR_ESR ())
757 {
758 /* We need to be in supervisor mode to swap the registers. Access the
759 PSR.S directly in order to avoid recursive context switches. */
760 int i;
761 int save_psr_s = CPU (h_psr_s);
762 CPU (h_psr_s) = 1;
763 for (i = 0; i < 4; ++i)
764 {
765 int gr = i + 4;
766 int spr = i + H_SPR_SR0;
767 SI tmp = GET_H_SPR (spr);
768 SET_H_SPR (spr, GET_H_GR (gr));
769 SET_H_GR (gr, tmp);
770 }
771 CPU (h_psr_s) = save_psr_s;
772 }
773}
774\f
775/* Handle load/store of quad registers. */
776void
777frvbf_load_quad_GR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix)
778{
779 int i;
780 SI value[4];
781
782 /* Check memory alignment */
783 address = check_memory_alignment (current_cpu, address, 0xf);
784
785 /* If we need to count cycles, then the cache operation will be
786 initiated from the model profiling functions.
787 See frvbf_model_.... */
788 if (model_insn)
789 {
790 CPU_LOAD_ADDRESS (current_cpu) = address;
791 CPU_LOAD_LENGTH (current_cpu) = 16;
792 }
793 else
794 {
795 for (i = 0; i < 4; ++i)
796 {
797 value[i] = frvbf_read_mem_SI (current_cpu, pc, address);
798 address += 4;
799 }
800 sim_queue_fn_xi_write (current_cpu, frvbf_h_gr_quad_set_handler, targ_ix,
801 value);
802 }
803}
804
805void
806frvbf_store_quad_GR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix)
807{
808 int i;
809 SI value[4];
810 USI hsr0;
811
812 /* Check register and memory alignment. */
813 src_ix = check_register_alignment (current_cpu, src_ix, 3);
814 address = check_memory_alignment (current_cpu, address, 0xf);
815
816 for (i = 0; i < 4; ++i)
817 {
818 /* GR0 is always 0. */
819 if (src_ix == 0)
820 value[i] = 0;
821 else
822 value[i] = GET_H_GR (src_ix + i);
823 }
824 hsr0 = GET_HSR0 ();
825 if (GET_HSR0_DCE (hsr0))
826 sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value);
827 else
828 sim_queue_mem_xi_write (current_cpu, address, value);
829}
830
831void
832frvbf_load_quad_FRint (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix)
833{
834 int i;
835 SI value[4];
836
837 /* Check memory alignment */
838 address = check_memory_alignment (current_cpu, address, 0xf);
839
840 /* If we need to count cycles, then the cache operation will be
841 initiated from the model profiling functions.
842 See frvbf_model_.... */
843 if (model_insn)
844 {
845 CPU_LOAD_ADDRESS (current_cpu) = address;
846 CPU_LOAD_LENGTH (current_cpu) = 16;
847 }
848 else
849 {
850 for (i = 0; i < 4; ++i)
851 {
852 value[i] = frvbf_read_mem_SI (current_cpu, pc, address);
853 address += 4;
854 }
855 sim_queue_fn_xi_write (current_cpu, frvbf_h_fr_quad_set_handler, targ_ix,
856 value);
857 }
858}
859
860void
861frvbf_store_quad_FRint (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix)
862{
863 int i;
864 SI value[4];
865 USI hsr0;
866
867 /* Check register and memory alignment. */
868 src_ix = check_fr_register_alignment (current_cpu, src_ix, 3);
869 address = check_memory_alignment (current_cpu, address, 0xf);
870
871 for (i = 0; i < 4; ++i)
872 value[i] = GET_H_FR (src_ix + i);
873
874 hsr0 = GET_HSR0 ();
875 if (GET_HSR0_DCE (hsr0))
876 sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value);
877 else
878 sim_queue_mem_xi_write (current_cpu, address, value);
879}
880
881void
882frvbf_load_quad_CPR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI targ_ix)
883{
884 int i;
885 SI value[4];
886
887 /* Check memory alignment */
888 address = check_memory_alignment (current_cpu, address, 0xf);
889
890 /* If we need to count cycles, then the cache operation will be
891 initiated from the model profiling functions.
892 See frvbf_model_.... */
893 if (model_insn)
894 {
895 CPU_LOAD_ADDRESS (current_cpu) = address;
896 CPU_LOAD_LENGTH (current_cpu) = 16;
897 }
898 else
899 {
900 for (i = 0; i < 4; ++i)
901 {
902 value[i] = frvbf_read_mem_SI (current_cpu, pc, address);
903 address += 4;
904 }
905 sim_queue_fn_xi_write (current_cpu, frvbf_h_cpr_quad_set_handler, targ_ix,
906 value);
907 }
908}
909
910void
911frvbf_store_quad_CPR (SIM_CPU *current_cpu, PCADDR pc, SI address, SI src_ix)
912{
913 int i;
914 SI value[4];
915 USI hsr0;
916
917 /* Check register and memory alignment. */
918 src_ix = check_register_alignment (current_cpu, src_ix, 3);
919 address = check_memory_alignment (current_cpu, address, 0xf);
920
921 for (i = 0; i < 4; ++i)
922 value[i] = GET_H_CPR (src_ix + i);
923
924 hsr0 = GET_HSR0 ();
925 if (GET_HSR0_DCE (hsr0))
926 sim_queue_fn_mem_xi_write (current_cpu, frvbf_mem_set_XI, address, value);
927 else
928 sim_queue_mem_xi_write (current_cpu, address, value);
929}
930\f
931void
932frvbf_signed_integer_divide (
933 SIM_CPU *current_cpu, SI arg1, SI arg2, int target_index, int non_excepting
934)
935{
936 enum frv_dtt dtt = FRV_DTT_NO_EXCEPTION;
937 if (arg1 == 0x80000000 && arg2 == -1)
938 {
939 /* 0x80000000/(-1) must result in 0x7fffffff when ISR.EDE is set
940 otherwise it may result in 0x7fffffff (sparc compatibility) or
941 0x80000000 (C language compatibility). */
942 USI isr;
943 dtt = FRV_DTT_OVERFLOW;
944
945 isr = GET_ISR ();
946 if (GET_ISR_EDE (isr))
947 sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index,
948 0x7fffffff);
949 else
950 sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index,
951 0x80000000);
952 frvbf_force_update (current_cpu); /* Force update of target register. */
953 }
954 else if (arg2 == 0)
955 dtt = FRV_DTT_DIVISION_BY_ZERO;
956 else
957 sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index,
958 arg1 / arg2);
959
960 /* Check for exceptions. */
961 if (dtt != FRV_DTT_NO_EXCEPTION)
962 dtt = frvbf_division_exception (current_cpu, dtt, target_index,
963 non_excepting);
964 if (non_excepting && dtt == FRV_DTT_NO_EXCEPTION)
965 {
966 /* Non excepting instruction. Clear the NE flag for the target
967 register. */
968 SI NE_flags[2];
969 GET_NE_FLAGS (NE_flags, H_SPR_GNER0);
970 CLEAR_NE_FLAG (NE_flags, target_index);
971 SET_NE_FLAGS (H_SPR_GNER0, NE_flags);
972 }
973}
974
975void
976frvbf_unsigned_integer_divide (
977 SIM_CPU *current_cpu, USI arg1, USI arg2, int target_index, int non_excepting
978)
979{
980 if (arg2 == 0)
981 frvbf_division_exception (current_cpu, FRV_DTT_DIVISION_BY_ZERO,
982 target_index, non_excepting);
983 else
984 {
985 sim_queue_fn_si_write (current_cpu, frvbf_h_gr_set, target_index,
986 arg1 / arg2);
987 if (non_excepting)
988 {
989 /* Non excepting instruction. Clear the NE flag for the target
990 register. */
991 SI NE_flags[2];
992 GET_NE_FLAGS (NE_flags, H_SPR_GNER0);
993 CLEAR_NE_FLAG (NE_flags, target_index);
994 SET_NE_FLAGS (H_SPR_GNER0, NE_flags);
995 }
996 }
997}
998\f
999/* Clear accumulators. */
1000void
1001frvbf_clear_accumulators (SIM_CPU *current_cpu, SI acc_ix, int A)
1002{
1003 SIM_DESC sd = CPU_STATE (current_cpu);
676a64f4
RS
1004 int acc_mask =
1005 (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500) ? 7 :
1006 (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) ? 7 :
1007 (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr450) ? 11 :
1008 (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400) ? 3 :
b34f6357 1009 63;
e930b1f5 1010 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
b34f6357 1011
e930b1f5
DB
1012 ps->mclracc_acc = acc_ix;
1013 ps->mclracc_A = A;
b34f6357
DB
1014 if (A == 0 || acc_ix != 0) /* Clear 1 accumuator? */
1015 {
1016 /* This instruction is a nop if the referenced accumulator is not
1017 implemented. */
676a64f4 1018 if ((acc_ix & acc_mask) == acc_ix)
b34f6357
DB
1019 sim_queue_fn_di_write (current_cpu, frvbf_h_acc40S_set, acc_ix, 0);
1020 }
1021 else
1022 {
1023 /* Clear all implemented accumulators. */
1024 int i;
676a64f4
RS
1025 for (i = 0; i <= acc_mask; ++i)
1026 if ((i & acc_mask) == i)
1027 sim_queue_fn_di_write (current_cpu, frvbf_h_acc40S_set, i, 0);
b34f6357
DB
1028 }
1029}
1030\f
1031/* Functions to aid insn semantics. */
1032
1033/* Compute the result of the SCAN and SCANI insns after the shift and xor. */
1034SI
1035frvbf_scan_result (SIM_CPU *current_cpu, SI value)
1036{
1037 SI i;
1038 SI mask;
1039
1040 if (value == 0)
1041 return 63;
1042
1043 /* Find the position of the first non-zero bit.
1044 The loop will terminate since there is guaranteed to be at least one
1045 non-zero bit. */
1046 mask = 1 << (sizeof (mask) * 8 - 1);
1047 for (i = 0; (value & mask) == 0; ++i)
1048 value <<= 1;
1049
1050 return i;
1051}
1052
1053/* Compute the result of the cut insns. */
1054SI
1055frvbf_cut (SIM_CPU *current_cpu, SI reg1, SI reg2, SI cut_point)
1056{
1057 SI result;
1058 if (cut_point < 32)
1059 {
1060 result = reg1 << cut_point;
1061 result |= (reg2 >> (32 - cut_point)) & ((1 << cut_point) - 1);
1062 }
1063 else
1064 result = reg2 << (cut_point - 32);
1065
1066 return result;
1067}
1068
1069/* Compute the result of the cut insns. */
1070SI
1071frvbf_media_cut (SIM_CPU *current_cpu, DI acc, SI cut_point)
1072{
1073 /* The cut point is the lower 6 bits (signed) of what we are passed. */
1074 cut_point = cut_point << 26 >> 26;
1075
1076 /* The cut_point is relative to bit 40 of 64 bits. */
1077 if (cut_point >= 0)
1078 return (acc << (cut_point + 24)) >> 32;
1079
1080 /* Extend the sign bit (bit 40) for negative cuts. */
1081 if (cut_point == -32)
1082 return (acc << 24) >> 63; /* Special case for full shiftout. */
1083
1084 return (acc << 24) >> (32 + -cut_point);
1085}
1086
1087/* Compute the result of the cut insns. */
1088SI
1089frvbf_media_cut_ss (SIM_CPU *current_cpu, DI acc, SI cut_point)
1090{
1091 /* The cut point is the lower 6 bits (signed) of what we are passed. */
1092 cut_point = cut_point << 26 >> 26;
1093
1094 if (cut_point >= 0)
1095 {
1096 /* The cut_point is relative to bit 40 of 64 bits. */
1097 DI shifted = acc << (cut_point + 24);
1098 DI unshifted = shifted >> (cut_point + 24);
1099
1100 /* The result will be saturated if significant bits are shifted out. */
1101 if (unshifted != acc)
1102 {
1103 if (acc < 0)
1104 return 0x80000000;
1105 return 0x7fffffff;
1106 }
1107 }
1108
1109 /* The result will not be saturated, so use the code for the normal cut. */
1110 return frvbf_media_cut (current_cpu, acc, cut_point);
1111}
1112
e930b1f5
DB
1113/* Compute the result of int accumulator cut (SCUTSS). */
1114SI
1115frvbf_iacc_cut (SIM_CPU *current_cpu, DI acc, SI cut_point)
1116{
8b73069f
RS
1117 DI lower, upper;
1118
1119 /* The cut point is the lower 7 bits (signed) of what we are passed. */
e930b1f5
DB
1120 cut_point = cut_point << 25 >> 25;
1121
8b73069f
RS
1122 /* Conceptually, the operation is on a 128-bit sign-extension of ACC.
1123 The top bit of the return value corresponds to bit (63 - CUT_POINT)
1124 of this 128-bit value.
e930b1f5 1125
8b73069f
RS
1126 Since we can't deal with 128-bit values very easily, convert the
1127 operation into an equivalent 64-bit one. */
e930b1f5 1128 if (cut_point < 0)
8b73069f
RS
1129 {
1130 /* Avoid an undefined shift operation. */
1131 if (cut_point == -64)
1132 acc >>= 63;
1133 else
1134 acc >>= -cut_point;
1135 cut_point = 0;
1136 }
e930b1f5 1137
8b73069f
RS
1138 /* Get the shifted but unsaturated result. Set LOWER to the lowest
1139 32 bits of the result and UPPER to the result >> 31. */
1140 if (cut_point < 32)
1141 {
1142 /* The cut loses the (32 - CUT_POINT) least significant bits.
1143 Round the result up if the most significant of these lost bits
1144 is 1. */
1145 lower = acc >> (32 - cut_point);
1146 if (lower < 0x7fffffff)
1147 if (acc & LSBIT64 (32 - cut_point - 1))
1148 lower++;
1149 upper = lower >> 31;
1150 }
1151 else
1152 {
1153 lower = acc << (cut_point - 32);
1154 upper = acc >> (63 - cut_point);
1155 }
e930b1f5 1156
8b73069f
RS
1157 /* Saturate the result. */
1158 if (upper < -1)
1159 return ~0x7fffffff;
1160 else if (upper > 0)
1161 return 0x7fffffff;
1162 else
1163 return lower;
e930b1f5
DB
1164}
1165
1166/* Compute the result of shift-left-arithmetic-with-saturation (SLASS). */
1167SI
1168frvbf_shift_left_arith_saturate (SIM_CPU *current_cpu, SI arg1, SI arg2)
1169{
1170 int neg_arg1;
1171
1172 /* FIXME: what to do with negative shift amt? */
1173 if (arg2 <= 0)
1174 return arg1;
1175
1176 if (arg1 == 0)
1177 return 0;
1178
1179 /* Signed shift by 31 or greater saturates by definition. */
1180 if (arg2 >= 31)
1181 if (arg1 > 0)
1182 return (SI) 0x7fffffff;
1183 else
1184 return (SI) 0x80000000;
1185
1186 /* OK, arg2 is between 1 and 31. */
1187 neg_arg1 = (arg1 < 0);
1188 do {
1189 arg1 <<= 1;
1190 /* Check for sign bit change (saturation). */
1191 if (neg_arg1 && (arg1 >= 0))
1192 return (SI) 0x80000000;
1193 else if (!neg_arg1 && (arg1 < 0))
1194 return (SI) 0x7fffffff;
1195 } while (--arg2 > 0);
1196
1197 return arg1;
1198}
1199
b34f6357
DB
1200/* Simulate the media custom insns. */
1201void
1202frvbf_media_cop (SIM_CPU *current_cpu, int cop_num)
1203{
1204 /* The semantics of the insn are a nop, since it is implementation defined.
1205 We do need to check whether it's implemented and set up for MTRAP
1206 if it's not. */
1207 USI msr0 = GET_MSR (0);
1208 if (GET_MSR_EMCI (msr0) == 0)
1209 {
1210 /* no interrupt queued at this time. */
1211 frv_set_mp_exception_registers (current_cpu, MTT_UNIMPLEMENTED_MPOP, 0);
1212 }
1213}
1214
1215/* Simulate the media average (MAVEH) insn. */
1216static HI
1217do_media_average (SIM_CPU *current_cpu, HI arg1, HI arg2)
1218{
1219 SIM_DESC sd = CPU_STATE (current_cpu);
1220 SI sum = (arg1 + arg2);
1221 HI result = sum >> 1;
f9e18f5a 1222 int rounding_value;
b34f6357 1223
676a64f4
RS
1224 /* On fr4xx and fr550, check the rounding mode. On other machines
1225 rounding is always toward negative infinity and the result is
1226 already correctly rounded. */
f9e18f5a 1227 switch (STATE_ARCHITECTURE (sd)->mach)
b34f6357 1228 {
f9e18f5a
DB
1229 /* Need to check rounding mode. */
1230 case bfd_mach_fr400:
676a64f4 1231 case bfd_mach_fr450:
e930b1f5 1232 case bfd_mach_fr550:
b34f6357
DB
1233 /* Check whether rounding will be required. Rounding will be required
1234 if the sum is an odd number. */
f9e18f5a 1235 rounding_value = sum & 1;
b34f6357
DB
1236 if (rounding_value)
1237 {
1238 USI msr0 = GET_MSR (0);
1239 /* Check MSR0.SRDAV to determine which bits control the rounding. */
1240 if (GET_MSR_SRDAV (msr0))
1241 {
1242 /* MSR0.RD controls rounding. */
1243 switch (GET_MSR_RD (msr0))
1244 {
1245 case 0:
1246 /* Round to nearest. */
1247 if (result >= 0)
1248 ++result;
1249 break;
1250 case 1:
1251 /* Round toward 0. */
1252 if (result < 0)
1253 ++result;
1254 break;
1255 case 2:
1256 /* Round toward positive infinity. */
1257 ++result;
1258 break;
1259 case 3:
1260 /* Round toward negative infinity. The result is already
1261 correctly rounded. */
1262 break;
1263 default:
1264 abort ();
1265 break;
1266 }
1267 }
1268 else
1269 {
1270 /* MSR0.RDAV controls rounding. If set, round toward positive
1271 infinity. Otherwise the result is already rounded correctly
1272 toward negative infinity. */
1273 if (GET_MSR_RDAV (msr0))
1274 ++result;
1275 }
1276 }
f9e18f5a
DB
1277 break;
1278 default:
1279 break;
b34f6357
DB
1280 }
1281
1282 return result;
1283}
1284
1285SI
1286frvbf_media_average (SIM_CPU *current_cpu, SI reg1, SI reg2)
1287{
1288 SI result;
1289 result = do_media_average (current_cpu, reg1 & 0xffff, reg2 & 0xffff);
1290 result &= 0xffff;
1291 result |= do_media_average (current_cpu, (reg1 >> 16) & 0xffff,
1292 (reg2 >> 16) & 0xffff) << 16;
1293 return result;
1294}
1295
1296/* Maintain a flag in order to know when to write the address of the next
1297 VLIW instruction into the LR register. Used by JMPL. JMPIL, and CALL. */
1298void
1299frvbf_set_write_next_vliw_addr_to_LR (SIM_CPU *current_cpu, int value)
1300{
1301 frvbf_write_next_vliw_addr_to_LR = value;
1302}
1303
1304void
1305frvbf_set_ne_index (SIM_CPU *current_cpu, int index)
1306{
1307 USI NE_flags[2];
1308
1309 /* Save the target register so interrupt processing can set its NE flag
1310 in the event of an exception. */
1311 frv_interrupt_state.ne_index = index;
1312
1313 /* Clear the NE flag of the target register. It will be reset if necessary
1314 in the event of an exception. */
1315 GET_NE_FLAGS (NE_flags, H_SPR_FNER0);
1316 CLEAR_NE_FLAG (NE_flags, index);
1317 SET_NE_FLAGS (H_SPR_FNER0, NE_flags);
1318}
1319
1320void
1321frvbf_force_update (SIM_CPU *current_cpu)
1322{
1323 CGEN_WRITE_QUEUE *q = CPU_WRITE_QUEUE (current_cpu);
1324 int ix = CGEN_WRITE_QUEUE_INDEX (q);
1325 if (ix > 0)
1326 {
1327 CGEN_WRITE_QUEUE_ELEMENT *item = CGEN_WRITE_QUEUE_ELEMENT (q, ix - 1);
1328 item->flags |= FRV_WRITE_QUEUE_FORCE_WRITE;
1329 }
1330}
1331\f
1332/* Condition code logic. */
1333enum cr_ops {
1334 andcr, orcr, xorcr, nandcr, norcr, andncr, orncr, nandncr, norncr,
1335 num_cr_ops
1336};
1337
1338enum cr_result {cr_undefined, cr_undefined1, cr_false, cr_true};
1339
1340static enum cr_result
1341cr_logic[num_cr_ops][4][4] = {
1342 /* andcr */
1343 {
1344 /* undefined undefined false true */
1345 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1346 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1347 /* false */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1348 /* true */ {cr_undefined, cr_undefined, cr_false, cr_true }
1349 },
1350 /* orcr */
1351 {
1352 /* undefined undefined false true */
1353 /* undefined */ {cr_undefined, cr_undefined, cr_false, cr_true },
1354 /* undefined */ {cr_undefined, cr_undefined, cr_false, cr_true },
1355 /* false */ {cr_false, cr_false, cr_false, cr_true },
1356 /* true */ {cr_true, cr_true, cr_true, cr_true }
1357 },
1358 /* xorcr */
1359 {
1360 /* undefined undefined false true */
1361 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1362 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1363 /* false */ {cr_undefined, cr_undefined, cr_false, cr_true },
1364 /* true */ {cr_true, cr_true, cr_true, cr_false }
1365 },
1366 /* nandcr */
1367 {
1368 /* undefined undefined false true */
1369 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1370 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1371 /* false */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1372 /* true */ {cr_undefined, cr_undefined, cr_true, cr_false }
1373 },
1374 /* norcr */
1375 {
1376 /* undefined undefined false true */
1377 /* undefined */ {cr_undefined, cr_undefined, cr_true, cr_false },
1378 /* undefined */ {cr_undefined, cr_undefined, cr_true, cr_false },
1379 /* false */ {cr_true, cr_true, cr_true, cr_false },
1380 /* true */ {cr_false, cr_false, cr_false, cr_false }
1381 },
1382 /* andncr */
1383 {
1384 /* undefined undefined false true */
1385 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1386 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1387 /* false */ {cr_undefined, cr_undefined, cr_false, cr_true },
1388 /* true */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}
1389 },
1390 /* orncr */
1391 {
1392 /* undefined undefined false true */
1393 /* undefined */ {cr_undefined, cr_undefined, cr_false, cr_true },
1394 /* undefined */ {cr_undefined, cr_undefined, cr_false, cr_true },
1395 /* false */ {cr_true, cr_true, cr_true, cr_true },
1396 /* true */ {cr_false, cr_false, cr_false, cr_true }
1397 },
1398 /* nandncr */
1399 {
1400 /* undefined undefined false true */
1401 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1402 /* undefined */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined},
1403 /* false */ {cr_undefined, cr_undefined, cr_true, cr_false },
1404 /* true */ {cr_undefined, cr_undefined, cr_undefined, cr_undefined}
1405 },
1406 /* norncr */
1407 {
1408 /* undefined undefined false true */
1409 /* undefined */ {cr_undefined, cr_undefined, cr_true, cr_false },
1410 /* undefined */ {cr_undefined, cr_undefined, cr_true, cr_false },
1411 /* false */ {cr_false, cr_false, cr_false, cr_false },
1412 /* true */ {cr_true, cr_true, cr_true, cr_false }
1413 }
1414};
1415
1416UQI
1417frvbf_cr_logic (SIM_CPU *current_cpu, SI operation, UQI arg1, UQI arg2)
1418{
1419 return cr_logic[operation][arg1][arg2];
1420}
1421\f
1422/* Cache Manipulation. */
1423void
1424frvbf_insn_cache_preload (SIM_CPU *current_cpu, SI address, USI length, int lock)
1425{
1426 /* If we need to count cycles, then the cache operation will be
1427 initiated from the model profiling functions.
1428 See frvbf_model_.... */
1429 int hsr0 = GET_HSR0 ();
1430 if (GET_HSR0_ICE (hsr0))
1431 {
1432 if (model_insn)
1433 {
1434 CPU_LOAD_ADDRESS (current_cpu) = address;
1435 CPU_LOAD_LENGTH (current_cpu) = length;
1436 CPU_LOAD_LOCK (current_cpu) = lock;
1437 }
1438 else
1439 {
1440 FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu);
1441 frv_cache_preload (cache, address, length, lock);
1442 }
1443 }
1444}
1445
1446void
1447frvbf_data_cache_preload (SIM_CPU *current_cpu, SI address, USI length, int lock)
1448{
1449 /* If we need to count cycles, then the cache operation will be
1450 initiated from the model profiling functions.
1451 See frvbf_model_.... */
1452 int hsr0 = GET_HSR0 ();
1453 if (GET_HSR0_DCE (hsr0))
1454 {
1455 if (model_insn)
1456 {
1457 CPU_LOAD_ADDRESS (current_cpu) = address;
1458 CPU_LOAD_LENGTH (current_cpu) = length;
1459 CPU_LOAD_LOCK (current_cpu) = lock;
1460 }
1461 else
1462 {
1463 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
1464 frv_cache_preload (cache, address, length, lock);
1465 }
1466 }
1467}
1468
1469void
1470frvbf_insn_cache_unlock (SIM_CPU *current_cpu, SI address)
1471{
1472 /* If we need to count cycles, then the cache operation will be
1473 initiated from the model profiling functions.
1474 See frvbf_model_.... */
1475 int hsr0 = GET_HSR0 ();
1476 if (GET_HSR0_ICE (hsr0))
1477 {
1478 if (model_insn)
1479 CPU_LOAD_ADDRESS (current_cpu) = address;
1480 else
1481 {
1482 FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu);
1483 frv_cache_unlock (cache, address);
1484 }
1485 }
1486}
1487
1488void
1489frvbf_data_cache_unlock (SIM_CPU *current_cpu, SI address)
1490{
1491 /* If we need to count cycles, then the cache operation will be
1492 initiated from the model profiling functions.
1493 See frvbf_model_.... */
1494 int hsr0 = GET_HSR0 ();
1495 if (GET_HSR0_DCE (hsr0))
1496 {
1497 if (model_insn)
1498 CPU_LOAD_ADDRESS (current_cpu) = address;
1499 else
1500 {
1501 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
1502 frv_cache_unlock (cache, address);
1503 }
1504 }
1505}
1506
1507void
1508frvbf_insn_cache_invalidate (SIM_CPU *current_cpu, SI address, int all)
1509{
1510 /* Make sure the insn was specified properly. -1 will be passed for ALL
1511 for a icei with A=0. */
1512 if (all == -1)
1513 {
1514 frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
1515 return;
1516 }
1517
1518 /* If we need to count cycles, then the cache operation will be
1519 initiated from the model profiling functions.
1520 See frvbf_model_.... */
1521 if (model_insn)
1522 {
1523 /* Record the all-entries flag for use in profiling. */
1524 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
1525 ps->all_cache_entries = all;
1526 CPU_LOAD_ADDRESS (current_cpu) = address;
1527 }
1528 else
1529 {
1530 FRV_CACHE *cache = CPU_INSN_CACHE (current_cpu);
1531 if (all)
1532 frv_cache_invalidate_all (cache, 0/* flush? */);
1533 else
1534 frv_cache_invalidate (cache, address, 0/* flush? */);
1535 }
1536}
1537
1538void
1539frvbf_data_cache_invalidate (SIM_CPU *current_cpu, SI address, int all)
1540{
1541 /* Make sure the insn was specified properly. -1 will be passed for ALL
1542 for a dcei with A=0. */
1543 if (all == -1)
1544 {
1545 frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
1546 return;
1547 }
1548
1549 /* If we need to count cycles, then the cache operation will be
1550 initiated from the model profiling functions.
1551 See frvbf_model_.... */
1552 if (model_insn)
1553 {
1554 /* Record the all-entries flag for use in profiling. */
1555 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
1556 ps->all_cache_entries = all;
1557 CPU_LOAD_ADDRESS (current_cpu) = address;
1558 }
1559 else
1560 {
1561 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
1562 if (all)
1563 frv_cache_invalidate_all (cache, 0/* flush? */);
1564 else
1565 frv_cache_invalidate (cache, address, 0/* flush? */);
1566 }
1567}
1568
1569void
1570frvbf_data_cache_flush (SIM_CPU *current_cpu, SI address, int all)
1571{
1572 /* Make sure the insn was specified properly. -1 will be passed for ALL
1573 for a dcef with A=0. */
1574 if (all == -1)
1575 {
1576 frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION);
1577 return;
1578 }
1579
1580 /* If we need to count cycles, then the cache operation will be
1581 initiated from the model profiling functions.
1582 See frvbf_model_.... */
1583 if (model_insn)
1584 {
1585 /* Record the all-entries flag for use in profiling. */
1586 FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu);
1587 ps->all_cache_entries = all;
1588 CPU_LOAD_ADDRESS (current_cpu) = address;
1589 }
1590 else
1591 {
1592 FRV_CACHE *cache = CPU_DATA_CACHE (current_cpu);
1593 if (all)
1594 frv_cache_invalidate_all (cache, 1/* flush? */);
1595 else
1596 frv_cache_invalidate (cache, address, 1/* flush? */);
1597 }
1598}
This page took 0.255903 seconds and 4 git commands to generate.