diff options
author | Mike Frysinger <vapier@gentoo.org> | 2011-06-18 20:04:32 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2011-06-18 20:04:32 +0000 |
commit | 388aa9fe20b5692d76ca36c61619bdb887d174b0 (patch) | |
tree | a032de16503cb20bc8a4bd0fcee086e9eded170e /sim/bfin | |
parent | f2a56d0ad70bc43ea8c56272ea1d5261b2028cb5 (diff) | |
download | gdb-388aa9fe20b5692d76ca36c61619bdb887d174b0.zip gdb-388aa9fe20b5692d76ca36c61619bdb887d174b0.tar.gz gdb-388aa9fe20b5692d76ca36c61619bdb887d174b0.tar.bz2 |
sim: bfin: handle V/VS saturation in dsp mac insns
Some saturation cases with dsp mac insns were not setting the V flag.
So implement that part and split up the logic between the dual macs.
Signed-off-by: Robin Getz <robin.getz@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'sim/bfin')
-rw-r--r-- | sim/bfin/ChangeLog | 10 | ||||
-rw-r--r-- | sim/bfin/bfin-sim.c | 73 |
2 files changed, 58 insertions, 25 deletions
diff --git a/sim/bfin/ChangeLog b/sim/bfin/ChangeLog index 4c3692f..27d38a7 100644 --- a/sim/bfin/ChangeLog +++ b/sim/bfin/ChangeLog @@ -1,5 +1,15 @@ 2011-06-18 Robin Getz <robin.getz@analog.com> + * bfin-sim.c (decode_macfunc): Add nosat_acc to track acc value + before saturation, set sat when more cases saturate, and set the + overflow bit based on these results. For M_TFU, M_IU, M_FU, and + M_W32, change the max values compared against. + (decode_dsp32mac_0): Delete v_i and add v_0 and v_1. Pass v_1 + when processing MAC1 and pass v_0 when processing MAC0. Combine + the results into the V/VS ASTAT bits. + +2011-06-18 Robin Getz <robin.getz@analog.com> + * bfin-sim.c (extract_mult): Call saturate_s32 when MM is set and mmod is M_IU. Call saturate_s16 when MM is set and mmod is M_TFU. diff --git a/sim/bfin/bfin-sim.c b/sim/bfin/bfin-sim.c index 71fda3e..d0ad051 100644 --- a/sim/bfin/bfin-sim.c +++ b/sim/bfin/bfin-sim.c @@ -1591,6 +1591,9 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0, if (op != 3) { bu8 sgn0 = (acc >> 31) & 1; + bu8 sgn40 = (acc >> 39) & 1; + bu40 nosat_acc; + /* This can't saturate, so we don't keep track of the sat flag. */ bu64 res = decode_multfunc (cpu, h0, h1, src0, src1, mmod, MM, &tsat); @@ -1610,6 +1613,7 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0, break; } + nosat_acc = acc; /* Saturate. */ switch (mmod) { @@ -1624,20 +1628,20 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0, acc = 0x7fffffffffull, sat = 1; break; case M_TFU: - if (!MM && acc > 0xFFFFFFFFFFull) - acc = 0x0, sat = 1; - if (MM && acc > 0xFFFFFFFF) - acc &= 0xFFFFFFFF; + if (!MM && (bs64)acc < 0) + acc = 0, sat = 1; + if (!MM && (bs64)acc > 0xFFFFFFFFFFull) + acc = 0xFFFFFFFFFFull, sat = 1; break; case M_IU: - if (acc & 0x8000000000000000ull) + if (!MM && acc & 0x8000000000000000ull) acc = 0x0, sat = 1; - if (acc > 0xFFFFFFFFFFull) - acc &= 0xFFFFFFFFFFull, sat = 1; - if (MM && acc > 0xFFFFFFFF) - acc &= 0xFFFFFFFF; - if (acc & 0x80000000) - acc |= 0xffffffff00000000ull; + if (!MM && acc > 0xFFFFFFFFFFull) + acc = 0xFFFFFFFFFFull, sat = 1; + if (MM && acc > 0xFFFFFFFFFFull) + acc &= 0xFFFFFFFFFFull; + if (acc & 0x8000000000ull) + acc |= 0xffffff0000000000ull; break; case M_FU: if (!MM && (bs64)acc < 0) @@ -1648,8 +1652,8 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0, acc = 0xFFFFFFFFFFull, sat = 1; if (MM && acc > 0xFFFFFFFFFFull) acc &= 0xFFFFFFFFFFull; - if (MM && acc & 0x80000000) - acc |= 0xffffffff00000000ull; + if (MM && acc & 0x8000000000ull) + acc |= 0xffffff0000000000ull; break; case M_IH: if ((bs64)acc < -0x80000000ll) @@ -1658,12 +1662,18 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0, acc = 0x7fffffffull, sat = 1; break; case M_W32: - if (sgn0 && (sgn0 != ((acc >> 31) & 1)) - && (((acc >> 32) & 0xFF) == 0xff)) - acc = 0x80000000; + /* check max negative value */ + if (sgn40 && ((acc >> 31) != 0x1ffffffff) + && ((acc >> 31) != 0x0)) + acc = 0x80000000, sat = 1; + if (!sat && !sgn40 && ((acc >> 31) != 0x0) + && ((acc >> 31) != 0x1ffffffff)) + acc = 0x7FFFFFFF, sat = 1; acc &= 0xffffffff; if (acc & 0x80000000) acc |= 0xffffffff00000000ull; + if (tsat) + sat = 1; break; default: illegal_instruction (cpu); @@ -1677,6 +1687,15 @@ decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0, STORE (ASTATREG (av[which]), sat); if (sat) STORE (ASTATREG (avs[which]), sat); + + /* Figure out the overflow bit. */ + if (sat) + { + if (fullword) + *overflow = 1; + else + ret = extract_mult (cpu, nosat_acc, mmod, MM, fullword, overflow); + } } ret = extract_mult (cpu, acc, mmod, MM, fullword, overflow); @@ -3727,7 +3746,7 @@ decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) int h01 = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask); bu32 res = DREG (dst); - bu32 v_i = 0, zero = 0, n_1 = 0, n_0 = 0; + bu32 v_0 = 0, v_1 = 0, zero = 0, n_1 = 0, n_0 = 0; static const char * const ops[] = { "=", "+=", "-=" }; char _buf[128], *buf = _buf; @@ -3752,7 +3771,7 @@ decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) if (w1 == 1 || op1 != 3) { bu32 res1 = decode_macfunc (cpu, 1, op1, h01, h11, src0, - src1, mmod, MM, P, &v_i, &n_1); + src1, mmod, MM, P, &v_1, &n_1); if (w1) buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P); @@ -3784,6 +3803,8 @@ decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) res = REG_H_L (res1 << 16, res); } } + else + v_1 = 0; if (w0 == 1 || op0 != 3) { @@ -3798,7 +3819,7 @@ decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) if (w0 == 1 || op0 != 3) { bu32 res0 = decode_macfunc (cpu, 0, op0, h00, h10, src0, - src1, mmod, 0, P, &v_i, &n_0); + src1, mmod, 0, P, &v_0, &n_0); if (w0) buf += sprintf (buf, P ? "R%i" : "R%i.L", dst); @@ -3830,6 +3851,8 @@ decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) res = REG_H_L (res, res0); } } + else + v_0 = 0; } TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM)); @@ -3837,15 +3860,15 @@ decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1) if (!P && (w0 || w1)) { STORE (DREG (dst), res); - SET_ASTATREG (v, v_i); - if (v_i) - SET_ASTATREG (vs, v_i); + SET_ASTATREG (v, v_0 | v_1); + if (v_0 || v_1) + SET_ASTATREG (vs, 1); } else if (P) { - SET_ASTATREG (v, v_i); - if (v_i) - SET_ASTATREG (vs, v_i); + SET_ASTATREG (v, v_0 | v_1); + if (v_0 || v_1) + SET_ASTATREG (vs, 1); } if ((w0 == 1 && op0 == 3) || (w1 == 1 && op1 == 3)) |