aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sim/bfin/ChangeLog11
-rw-r--r--sim/bfin/bfin-sim.c98
2 files changed, 64 insertions, 45 deletions
diff --git a/sim/bfin/ChangeLog b/sim/bfin/ChangeLog
index bac48f3..35863c9 100644
--- a/sim/bfin/ChangeLog
+++ b/sim/bfin/ChangeLog
@@ -1,3 +1,14 @@
+2012-03-19 Robin Getz <robin.getz@analog.com>
+ Mike Frysinger <vapier@gentoo.org>
+
+ * bfin-sim.c (lshift): Add an overflow flag. Delete now unused
+ i, j, and tmp vars. Add a new v_i var. Split the overflow logic
+ out from the saturate logic. Do not set V ASTAT bits when working
+ with accumulators.
+ (decode_ALU2op_0): Add new argument to lshift call.
+ (decode_LOGI2op_0, decode_dsp32shift_0, decode_dsp32shiftimm_0):
+ Likewise.
+
2012-03-18 Mike Frysinger <vapier@gentoo.org>
* dv-bfin_ebiu_amc.c (struct bfin_ebiu_amc): Add bank_base.
diff --git a/sim/bfin/bfin-sim.c b/sim/bfin/bfin-sim.c
index ef7362b..2c93e04 100644
--- a/sim/bfin/bfin-sim.c
+++ b/sim/bfin/bfin-sim.c
@@ -748,12 +748,12 @@ lshiftrt (SIM_CPU *cpu, bu64 val, int cnt, int size)
}
static bu64
-lshift (SIM_CPU *cpu, bu64 val, int cnt, int size, bool saturate)
+lshift (SIM_CPU *cpu, bu64 val, int cnt, int size, bool saturate, bool overflow)
{
- int i, j, real_cnt = cnt > size ? size : cnt;
+ int v_i, real_cnt = cnt > size ? size : cnt;
bu64 sgn = ~((val >> (size - 1)) - 1);
int mask_cnt = size - 1;
- bu64 masked, new_val = val, tmp;
+ bu64 masked, new_val = val;
bu64 mask = ~0;
mask <<= mask_cnt;
@@ -777,31 +777,35 @@ lshift (SIM_CPU *cpu, bu64 val, int cnt, int size, bool saturate)
However, it's a little more complex than looking at sign bits, we need
to see if we are shifting the sign information away... */
- tmp = val & ((~mask << 1) | 1);
-
- j = 0;
- for (i = 1; i <= real_cnt && saturate; i++)
- {
- if ((tmp & ((bu64)1 << (size - 1))) !=
- (((val >> mask_cnt) & 0x1) << mask_cnt))
- j++;
- tmp <<= 1;
- }
- saturate &= (!sgn && (new_val & (1 << mask_cnt)))
- || (sgn && !(new_val & (1 << mask_cnt)));
+ if (((val << cnt) >> size) == 0
+ || (((val << cnt) >> size) == ~(~0 << cnt)
+ && ((new_val >> (size - 1)) & 0x1)))
+ v_i = 0;
+ else
+ v_i = 1;
switch (size)
{
case 16:
- if (j || (saturate && (new_val & mask)))
- new_val = sgn == 0 ? 0x7fff : 0x8000, saturate = 1;
new_val &= 0xFFFF;
+ if (saturate && (v_i || ((val >> (size - 1)) != (new_val >> (size - 1)))))
+ {
+ new_val = (val >> (size - 1)) == 0 ? 0x7fff : 0x8000;
+ v_i = 1;
+ }
break;
case 32:
new_val &= 0xFFFFFFFF;
masked &= 0xFFFFFFFF;
- if (j || (saturate && ((sgn != masked) || (!sgn && new_val == 0))))
- new_val = sgn == 0 ? 0x7fffffff : 0x80000000, saturate = 1;
+ sgn &= 0xFFFFFFFF;
+ if (saturate
+ && (v_i
+ || (sgn != masked)
+ || (!sgn && new_val == 0 && val != 0)))
+ {
+ new_val = sgn == 0 ? 0x7fffffff : 0x80000000;
+ v_i = 1;
+ }
break;
case 40:
new_val &= 0xFFFFFFFFFFull;
@@ -814,9 +818,13 @@ lshift (SIM_CPU *cpu, bu64 val, int cnt, int size, bool saturate)
SET_ASTATREG (an, new_val >> (size - 1));
SET_ASTATREG (az, new_val == 0);
- SET_ASTATREG (v, !!(saturate || j));
- if (saturate || j)
- SET_ASTATREG (vs, 1);
+ if (size != 40)
+ {
+ SET_ASTATREG (v, overflow && v_i);
+ if (overflow && v_i)
+ SET_ASTATREG (vs, 1);
+ }
+
return new_val;
}
@@ -2557,7 +2565,7 @@ decode_ALU2op_0 (SIM_CPU *cpu, bu16 iw0)
else if (opc == 2)
{
TRACE_INSN (cpu, "R%i <<= R%i;", dst, src);
- SET_DREG (dst, lshift (cpu, DREG (dst), DREG (src), 32, 0));
+ SET_DREG (dst, lshift (cpu, DREG (dst), DREG (src), 32, 0, 0));
}
else if (opc == 3)
{
@@ -2760,7 +2768,7 @@ decode_LOGI2op_0 (SIM_CPU *cpu, bu16 iw0)
TRACE_INSN (cpu, "R%i <<= %s;", dst, uimm_str);
if (INSN_LEN == 8)
illegal_instruction_combination (cpu);
- SET_DREG (dst, lshift (cpu, DREG (dst), uimm, 32, 0));
+ SET_DREG (dst, lshift (cpu, DREG (dst), uimm, 32, 0, 0));
}
}
@@ -5158,7 +5166,7 @@ decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
if (shft <= 0)
val = ashiftrt (cpu, val, -shft, 16);
else
- val = lshift (cpu, val, shft, 16, sop == 1);
+ val = lshift (cpu, val, shft, 16, sop == 1, 1);
if ((HLs & 2) == 0)
STORE (DREG (dst0), REG_H_L (DREG (dst0), val));
@@ -5219,7 +5227,7 @@ decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
if (shft <= 0)
val = ashiftrt (cpu, val, -shft, 40);
else
- val = lshift (cpu, val, shft, 40, 0);
+ val = lshift (cpu, val, shft, 40, 0, 0);
STORE (AXREG (HLs), (val >> 32) & 0xff);
STORE (AWREG (HLs), (val & 0xffffffff));
@@ -5239,7 +5247,7 @@ decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
if (shft <= 0)
val = lshiftrt (cpu, val, -shft, 40);
else
- val = lshift (cpu, val, shft, 40, 0);
+ val = lshift (cpu, val, shft, 40, 0, 0);
STORE (AXREG (HLs), (val >> 32) & 0xff);
STORE (AWREG (HLs), (val & 0xffffffff));
@@ -5267,9 +5275,9 @@ decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
}
else
{
- val0 = lshift (cpu, val0, shft, 16, sop == 1);
+ val0 = lshift (cpu, val0, shft, 16, sop == 1, 1);
astat = ASTAT;
- val1 = lshift (cpu, val1, shft, 16, sop == 1);
+ val1 = lshift (cpu, val1, shft, 16, sop == 1, 1);
}
SET_ASTAT (ASTAT | astat);
STORE (DREG (dst0), (val1 << 16) | val0);
@@ -5294,7 +5302,7 @@ decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
STORE (DREG (dst0), ashiftrt (cpu, v, -shft, 32));
}
else
- STORE (DREG (dst0), lshift (cpu, v, shft, 32, sop == 1));
+ STORE (DREG (dst0), lshift (cpu, v, shft, 32, sop == 1, 1));
}
else if (sop == 3 && sopcde == 2)
{
@@ -5330,9 +5338,9 @@ decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
}
else
{
- val0 = lshift (cpu, val0, shft, 16, 0);
+ val0 = lshift (cpu, val0, shft, 16, 0, 0);
astat = ASTAT;
- val1 = lshift (cpu, val1, shft, 16, 0);
+ val1 = lshift (cpu, val1, shft, 16, 0, 0);
}
SET_ASTAT (ASTAT | astat);
STORE (DREG (dst0), (val1 << 16) | val0);
@@ -5702,7 +5710,7 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
dst0, (HLs & 2) ? 'H' : 'L',
src1, (HLs & 1) ? 'H' : 'L', newimmag);
if (newimmag > 16)
- result = lshift (cpu, in, 16 - (newimmag & 0xF), 16, 0);
+ result = lshift (cpu, in, 16 - (newimmag & 0xF), 16, 0, 1);
else
result = ashiftrt (cpu, in, newimmag, 16);
}
@@ -5711,14 +5719,14 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i (S);",
dst0, (HLs & 2) ? 'H' : 'L',
src1, (HLs & 1) ? 'H' : 'L', immag);
- result = lshift (cpu, in, immag, 16, 1);
+ result = lshift (cpu, in, immag, 16, 1, 1);
}
else if (sop == 1 && bit8)
{
TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i (S);",
dst0, (HLs & 2) ? 'H' : 'L',
src1, (HLs & 1) ? 'H' : 'L', immag);
- result = lshift (cpu, in, immag, 16, 1);
+ result = lshift (cpu, in, immag, 16, 1, 1);
}
else if (sop == 2 && bit8)
{
@@ -5732,7 +5740,7 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i;",
dst0, (HLs & 2) ? 'H' : 'L',
src1, (HLs & 1) ? 'H' : 'L', immag);
- result = lshift (cpu, in, immag, 16, 0);
+ result = lshift (cpu, in, immag, 16, 0, 1);
}
else
illegal_instruction (cpu);
@@ -5820,9 +5828,9 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
TRACE_INSN (cpu, "R%i = R%i << %i (V,S);", dst0, src1, count);
if (count >= 0)
{
- val0 = lshift (cpu, val0, count, 16, 1);
+ val0 = lshift (cpu, val0, count, 16, 1, 1);
astat = ASTAT;
- val1 = lshift (cpu, val1, count, 16, 1);
+ val1 = lshift (cpu, val1, count, 16, 1, 1);
}
else
{
@@ -5857,9 +5865,9 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
bu32 astat;
TRACE_INSN (cpu, "R%i = R%i << %i (V);", dst0, src1, count);
- val0 = lshift (cpu, val0, count, 16, 0);
+ val0 = lshift (cpu, val0, count, 16, 0, 1);
astat = ASTAT;
- val1 = lshift (cpu, val1, count, 16, 0);
+ val1 = lshift (cpu, val1, count, 16, 0, 1);
SET_ASTAT (ASTAT | astat);
STORE (DREG (dst0), val0 | (val1 << 16));
@@ -5876,9 +5884,9 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
if (count & 0x10)
{
- val0 = lshift (cpu, val0, 16 - (count & 0xF), 16, 0);
+ val0 = lshift (cpu, val0, 16 - (count & 0xF), 16, 0, 1);
astat = ASTAT;
- val1 = lshift (cpu, val1, 16 - (count & 0xF), 16, 0);
+ val1 = lshift (cpu, val1, 16 - (count & 0xF), 16, 0, 1);
}
else
{
@@ -5896,7 +5904,7 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
int count = imm6 (immag);
TRACE_INSN (cpu, "R%i = R%i << %i (S);", dst0, src1, count);
- STORE (DREG (dst0), lshift (cpu, DREG (src1), count, 32, 1));
+ STORE (DREG (dst0), lshift (cpu, DREG (src1), count, 32, 1, 1));
}
else if (sop == 2 && sopcde == 2)
{
@@ -5905,7 +5913,7 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
TRACE_INSN (cpu, "R%i = R%i >> %i;", dst0, src1, count);
if (count < 0)
- STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0));
+ STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0, 1));
else
STORE (DREG (dst0), lshiftrt (cpu, DREG (src1), count, 32));
}
@@ -5931,7 +5939,7 @@ decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
TRACE_INSN (cpu, "R%i = R%i >>> %i;", dst0, src1, count);
if (count < 0)
- STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0));
+ STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0, 1));
else
STORE (DREG (dst0), ashiftrt (cpu, DREG (src1), count, 32));
}