diff options
author | Dave Brolley <brolley@redhat.com> | 2003-10-08 18:19:33 +0000 |
---|---|---|
committer | Dave Brolley <brolley@redhat.com> | 2003-10-08 18:19:33 +0000 |
commit | e930b1f54ff2768c5818eb0a450b1d98d46d273d (patch) | |
tree | beff79b0fd16e78faffe78489d34d064d5618b43 /sim/frv/frv.c | |
parent | 7c3f9ad027b9ec2906f3367ca7be18e5fb8f6893 (diff) | |
download | binutils-e930b1f54ff2768c5818eb0a450b1d98d46d273d.tar.gz binutils-e930b1f54ff2768c5818eb0a450b1d98d46d273d.tar.bz2 binutils-e930b1f54ff2768c5818eb0a450b1d98d46d273d.zip |
2003-10-06 Dave Brolley <brolley@redhat.com>
* profile-fr550.[ch]: New files.
* configure.in: Move frv handling to alphabetically correct placement.
* Makefile.in: Add fr550 support.
* frv-sim.h,frv.c,interrups.c,memory.c,mloop.in,pipeline.c,
profile.[ch],registers.c,traps.c: Add fr550 support.
* arch.c,arch.h,cpu.c,cpu.h,cpuall.h,model.h,decode.c,decode.h,sem.c:
Regenerate.
Diffstat (limited to 'sim/frv/frv.c')
-rw-r--r-- | sim/frv/frv.c | 71 |
1 files changed, 70 insertions, 1 deletions
diff --git a/sim/frv/frv.c b/sim/frv/frv.c index bd3220dcacf..7f48256aa75 100644 --- a/sim/frv/frv.c +++ b/sim/frv/frv.c @@ -113,6 +113,7 @@ check_register_alignment (SIM_CPU *current_cpu, UINT reg, int align_mask) switch (STATE_ARCHITECTURE (sd)->mach) { case bfd_mach_fr400: + case bfd_mach_fr550: frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); break; case bfd_mach_frvtomcat: @@ -140,6 +141,7 @@ check_fr_register_alignment (SIM_CPU *current_cpu, UINT reg, int align_mask) switch (STATE_ARCHITECTURE (sd)->mach) { case bfd_mach_fr400: + case bfd_mach_fr550: frv_queue_program_interrupt (current_cpu, FRV_ILLEGAL_INSTRUCTION); break; case bfd_mach_frvtomcat: @@ -431,6 +433,9 @@ frvbf_h_spr_set_handler (SIM_CPU *current_cpu, UINT spr, USI newval) case H_SPR_SR3: spr_sr_set_handler (current_cpu, spr, newval); break; + case H_SPR_IHSR8: + frv_cache_reconfigure (current_cpu, CPU_INSN_CACHE (current_cpu)); + break; default: CPU (h_spr[spr]) = newval; break; @@ -926,9 +931,13 @@ frvbf_clear_accumulators (SIM_CPU *current_cpu, SI acc_ix, int A) SIM_DESC sd = CPU_STATE (current_cpu); int acc_num = (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr500) ? 8 : + (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr550) ? 8 : (STATE_ARCHITECTURE (sd)->mach == bfd_mach_fr400) ? 4 : 63; + FRV_PROFILE_STATE *ps = CPU_PROFILE_STATE (current_cpu); + ps->mclracc_acc = acc_ix; + ps->mclracc_A = A; if (A == 0 || acc_ix != 0) /* Clear 1 accumuator? */ { /* This instruction is a nop if the referenced accumulator is not @@ -1027,6 +1036,65 @@ frvbf_media_cut_ss (SIM_CPU *current_cpu, DI acc, SI cut_point) return frvbf_media_cut (current_cpu, acc, cut_point); } +/* Compute the result of int accumulator cut (SCUTSS). */ +SI +frvbf_iacc_cut (SIM_CPU *current_cpu, DI acc, SI cut_point) +{ + /* The cut point is the lower 6 bits (signed) of what we are passed. */ + cut_point = cut_point << 25 >> 25; + + if (cut_point <= -32) + cut_point = -31; /* Special case for full shiftout. */ + + /* Negative cuts (cannot saturate). */ + if (cut_point < 0) + return acc >> (32 + -cut_point); + + /* Positive cuts will saturate if significant bits are shifted out. */ + if (acc != ((acc << cut_point) >> cut_point)) + if (acc >= 0) + return 0x7fffffff; + else + return 0x80000000; + + /* No saturate, just cut. */ + return ((acc << cut_point) >> 32); +} + +/* Compute the result of shift-left-arithmetic-with-saturation (SLASS). */ +SI +frvbf_shift_left_arith_saturate (SIM_CPU *current_cpu, SI arg1, SI arg2) +{ + int neg_arg1; + + /* FIXME: what to do with negative shift amt? */ + if (arg2 <= 0) + return arg1; + + if (arg1 == 0) + return 0; + + /* Signed shift by 31 or greater saturates by definition. */ + if (arg2 >= 31) + if (arg1 > 0) + return (SI) 0x7fffffff; + else + return (SI) 0x80000000; + + /* OK, arg2 is between 1 and 31. */ + neg_arg1 = (arg1 < 0); + do { + arg1 <<= 1; + /* Check for sign bit change (saturation). */ + if (neg_arg1 && (arg1 >= 0)) + return (SI) 0x80000000; + else if (!neg_arg1 && (arg1 < 0)) + return (SI) 0x7fffffff; + } while (--arg2 > 0); + + return arg1; +} + /* Simulate the media custom insns. */ void frvbf_media_cop (SIM_CPU *current_cpu, int cop_num) @@ -1051,12 +1119,13 @@ do_media_average (SIM_CPU *current_cpu, HI arg1, HI arg2) HI result = sum >> 1; int rounding_value; - /* On fr400, check the rounding mode. On other machines rounding is always + /* On fr400 and fr550, check the rounding mode. On other machines rounding is always toward negative infinity and the result is already correctly rounded. */ switch (STATE_ARCHITECTURE (sd)->mach) { /* Need to check rounding mode. */ case bfd_mach_fr400: + case bfd_mach_fr550: /* Check whether rounding will be required. Rounding will be required if the sum is an odd number. */ rounding_value = sum & 1; |