aboutsummaryrefslogtreecommitdiff
path: root/sim/v850/simops.c
diff options
context:
space:
mode:
authorDJ Delorie <dj@redhat.com>2008-02-06 00:40:05 +0000
committerDJ Delorie <dj@redhat.com>2008-02-06 00:40:05 +0000
commitc5fbc25baf8de20a337383d4785dd4e15da428b0 (patch)
tree949d697d1bf9d65ba3a3bbabde25ec43fe9c9c49 /sim/v850/simops.c
parente5c4eb7a6c1d03decdb318b5a9e43719f207f460 (diff)
downloadfsf-binutils-gdb-c5fbc25baf8de20a337383d4785dd4e15da428b0.zip
fsf-binutils-gdb-c5fbc25baf8de20a337383d4785dd4e15da428b0.tar.gz
fsf-binutils-gdb-c5fbc25baf8de20a337383d4785dd4e15da428b0.tar.bz2
Index: ChangeLog
* configure.ac (v850): V850 now has a testsuite. * configure (v850): Likewise. Index: testsuite/ChangeLog * sim/v850/: New directory. * sim/v850/allinsns.exp: New. * sim/v850/bsh.cgs: New. * sim/v850/div.cgs: New. * sim/v850/divh.cgs: New. * sim/v850/divh_3.cgs: New. * sim/v850/divhu.cgs: New. * sim/v850/divu.cgs: New. * sim/v850/sar.cgs: New. * sim/v850/satadd.cgs: New. * sim/v850/satsub.cgs: New. * sim/v850/satsubi.cgs: New. * sim/v850/satsubr.cgs: New. * sim/v850/shl.cgs: New. * sim/v850/shr.cgs: New. * sim/v850/testutils.cgs: New. * sim/v850/testutils.inc: New. Index: v850/ChangeLog * simops.c (OP_C0): Correct saturation logic. (OP_220): Likewise. (OP_A0): Likewise. (OP_660): Likewise. (OP_80): Likewise. * simops.c (OP_2A0): If the shift count is zero, clear the carry. (OP_A007E0): Likewise. (OP_2C0): Likewise. (OP_C007E0): Likewise. (OP_280): Likewise. (OP_8007E0): Likewise. * simops.c (OP_2C207E0): Correct PSW flags for special divu conditions. (OP_2C007E0): Likewise, for div. (OP_28207E0): Likewise, for divhu. (OP_28007E0): Likewise, for divh. Also, sign-extend the correct operand. * v850.igen (divh): Likewise, for 2-op divh. * v850.igen (bsh): Fix carry logic.
Diffstat (limited to 'sim/v850/simops.c')
-rw-r--r--sim/v850/simops.c233
1 files changed, 151 insertions, 82 deletions
diff --git a/sim/v850/simops.c b/sim/v850/simops.c
index 38ec0a6..5513341 100644
--- a/sim/v850/simops.c
+++ b/sim/v850/simops.c
@@ -864,18 +864,29 @@ OP_C0 ()
&& (op0 & 0x80000000) != (result & 0x80000000));
sat = ov;
+ /* Handle saturated results. */
+ if (sat && s)
+ {
+ /* An overflow that results in a negative result implies that we
+ became too positive. */
+ result = 0x7fffffff;
+ s = 0;
+ }
+ else if (sat)
+ {
+ /* Any other overflow must have thus been too negative. */
+ result = 0x80000000;
+ s = 1;
+ z = 0;
+ }
+
/* Store the result and condition codes. */
State.regs[OP[1]] = result;
PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
| (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
| (sat ? PSW_SAT : 0));
-
- /* Handle saturated results. */
- if (sat && s)
- State.regs[OP[1]] = 0x80000000;
- else if (sat)
- State.regs[OP[1]] = 0x7fffffff;
+
trace_output (OP_REG_REG);
return 2;
@@ -905,18 +916,28 @@ OP_220 ()
&& (op0 & 0x80000000) != (result & 0x80000000));
sat = ov;
+ /* Handle saturated results. */
+ if (sat && s)
+ {
+ /* An overflow that results in a negative result implies that we
+ became too positive. */
+ result = 0x7fffffff;
+ s = 0;
+ }
+ else if (sat)
+ {
+ /* Any other overflow must have thus been too negative. */
+ result = 0x80000000;
+ s = 1;
+ z = 0;
+ }
+
/* Store the result and condition codes. */
State.regs[OP[1]] = result;
PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
PSW |= ((z ? PSW_Z : 0) | (s ? PSW_S : 0)
| (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
| (sat ? PSW_SAT : 0));
-
- /* Handle saturated results. */
- if (sat && s)
- State.regs[OP[1]] = 0x80000000;
- else if (sat)
- State.regs[OP[1]] = 0x7fffffff;
trace_output (OP_IMM_REG);
return 2;
@@ -942,7 +963,23 @@ OP_A0 ()
ov = ((op1 & 0x80000000) != (op0 & 0x80000000)
&& (op1 & 0x80000000) != (result & 0x80000000));
sat = ov;
-
+
+ /* Handle saturated results. */
+ if (sat && s)
+ {
+ /* An overflow that results in a negative result implies that we
+ became too positive. */
+ result = 0x7fffffff;
+ s = 0;
+ }
+ else if (sat)
+ {
+ /* Any other overflow must have thus been too negative. */
+ result = 0x80000000;
+ s = 1;
+ z = 0;
+ }
+
/* Store the result and condition codes. */
State.regs[OP[1]] = result;
PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
@@ -950,11 +987,6 @@ OP_A0 ()
| (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
| (sat ? PSW_SAT : 0));
- /* Handle saturated results. */
- if (sat && s)
- State.regs[OP[1]] = 0x80000000;
- else if (sat)
- State.regs[OP[1]] = 0x7fffffff;
trace_output (OP_REG_REG);
return 2;
}
@@ -982,6 +1014,22 @@ OP_660 ()
&& (op1 & 0x80000000) != (result & 0x80000000));
sat = ov;
+ /* Handle saturated results. */
+ if (sat && s)
+ {
+ /* An overflow that results in a negative result implies that we
+ became too positive. */
+ result = 0x7fffffff;
+ s = 0;
+ }
+ else if (sat)
+ {
+ /* Any other overflow must have thus been too negative. */
+ result = 0x80000000;
+ s = 1;
+ z = 0;
+ }
+
/* Store the result and condition codes. */
State.regs[OP[1]] = result;
PSW &= ~(PSW_Z | PSW_S | PSW_CY | PSW_OV);
@@ -989,11 +1037,6 @@ OP_660 ()
| (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
| (sat ? PSW_SAT : 0));
- /* Handle saturated results. */
- if (sat && s)
- State.regs[OP[1]] = 0x80000000;
- else if (sat)
- State.regs[OP[1]] = 0x7fffffff;
trace_output (OP_IMM_REG);
return 4;
@@ -1015,10 +1058,26 @@ OP_80 ()
/* Compute the condition codes. */
z = (result == 0);
s = (result & 0x80000000);
- cy = (result < op0);
- ov = ((op1 & 0x80000000) != (op0 & 0x80000000)
- && (op1 & 0x80000000) != (result & 0x80000000));
+ cy = (op0 < op1);
+ ov = ((op0 & 0x80000000) != (op1 & 0x80000000)
+ && (op0 & 0x80000000) != (result & 0x80000000));
sat = ov;
+
+ /* Handle saturated results. */
+ if (sat && s)
+ {
+ /* An overflow that results in a negative result implies that we
+ became too positive. */
+ result = 0x7fffffff;
+ s = 0;
+ }
+ else if (sat)
+ {
+ /* Any other overflow must have thus been too negative. */
+ result = 0x80000000;
+ s = 1;
+ z = 0;
+ }
/* Store the result and condition codes. */
State.regs[OP[1]] = result;
@@ -1027,11 +1086,6 @@ OP_80 ()
| (cy ? PSW_CY : 0) | (ov ? PSW_OV : 0)
| (sat ? PSW_SAT : 0));
- /* Handle saturated results. */
- if (sat && s)
- State.regs[OP[1]] = 0x80000000;
- else if (sat)
- State.regs[OP[1]] = 0x7fffffff;
trace_output (OP_REG_REG);
return 2;
@@ -1104,7 +1158,7 @@ OP_2A0 ()
/* Compute the condition codes. */
z = (result == 0);
s = (result & 0x80000000);
- cy = (op1 & (1 << (op0 - 1)));
+ cy = op0 ? (op1 & (1 << (op0 - 1))) : 0;
/* Store the result and condition codes. */
State.regs[ OP[1] ] = result;
@@ -1131,7 +1185,7 @@ OP_A007E0 ()
/* Compute the condition codes. */
z = (result == 0);
s = (result & 0x80000000);
- cy = (op1 & (1 << (op0 - 1)));
+ cy = op0 ? (op1 & (1 << (op0 - 1))) : 0;
/* Store the result and condition codes. */
State.regs[OP[1]] = result;
@@ -1157,7 +1211,7 @@ OP_2C0 ()
/* Compute the condition codes. */
z = (result == 0);
s = (result & 0x80000000);
- cy = (op1 & (1 << (32 - op0)));
+ cy = op0 ? (op1 & (1 << (32 - op0))) : 0;
/* Store the result and condition codes. */
State.regs[OP[1]] = result;
@@ -1183,7 +1237,7 @@ OP_C007E0 ()
/* Compute the condition codes. */
z = (result == 0);
s = (result & 0x80000000);
- cy = (op1 & (1 << (32 - op0)));
+ cy = op0 ? (op1 & (1 << (32 - op0))) : 0;
/* Store the result and condition codes. */
State.regs[OP[1]] = result;
@@ -1209,7 +1263,7 @@ OP_280 ()
/* Compute the condition codes. */
z = (result == 0);
s = (result & 0x80000000);
- cy = (op1 & (1 << (op0 - 1)));
+ cy = op0 ? (op1 & (1 << (op0 - 1))) : 0;
/* Store the result and condition codes. */
State.regs[OP[1]] = result;
@@ -1235,7 +1289,7 @@ OP_8007E0 ()
/* Compute the condition codes. */
z = (result == 0);
s = (result & 0x80000000);
- cy = (op1 & (1 << (op0 - 1)));
+ cy = op0 ? (op1 & (1 << (op0 - 1))) : 0;
/* Store the result and condition codes. */
State.regs[OP[1]] = result;
@@ -2264,19 +2318,20 @@ OP_2C207E0 (void)
if (divide_by == 0)
{
- overflow = 1;
- divide_by = 1;
+ PSW |= PSW_OV;
}
+ else
+ {
+ State.regs[ OP[1] ] = quotient = divide_this / divide_by;
+ State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
- State.regs[ OP[1] ] = quotient = divide_this / divide_by;
- State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
+ /* Set condition codes. */
+ PSW &= ~(PSW_Z | PSW_S | PSW_OV);
- /* Set condition codes. */
- PSW &= ~(PSW_Z | PSW_S | PSW_OV);
-
- if (overflow) PSW |= PSW_OV;
- if (quotient == 0) PSW |= PSW_Z;
- if (quotient & 0x80000000) PSW |= PSW_S;
+ if (overflow) PSW |= PSW_OV;
+ if (quotient == 0) PSW |= PSW_Z;
+ if (quotient & 0x80000000) PSW |= PSW_S;
+ }
trace_output (OP_REG_REG_REG);
@@ -2291,7 +2346,6 @@ OP_2C007E0 (void)
signed long int remainder;
signed long int divide_by;
signed long int divide_this;
- int overflow = 0;
trace_input ("div", OP_REG_REG_REG, 0);
@@ -2300,21 +2354,28 @@ OP_2C007E0 (void)
divide_by = State.regs[ OP[0] ];
divide_this = State.regs[ OP[1] ];
- if (divide_by == 0 || (divide_by == -1 && divide_this == (1 << 31)))
+ if (divide_by == 0)
{
- overflow = 1;
- divide_by = 1;
+ PSW |= PSW_OV;
}
+ else if (divide_by == -1 && divide_this == (1 << 31))
+ {
+ PSW &= ~PSW_Z;
+ PSW |= PSW_OV | PSW_S;
+ State.regs[ OP[1] ] = (1 << 31);
+ State.regs[ OP[2] >> 11 ] = 0;
+ }
+ else
+ {
+ State.regs[ OP[1] ] = quotient = divide_this / divide_by;
+ State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
- State.regs[ OP[1] ] = quotient = divide_this / divide_by;
- State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
-
- /* Set condition codes. */
- PSW &= ~(PSW_Z | PSW_S | PSW_OV);
+ /* Set condition codes. */
+ PSW &= ~(PSW_Z | PSW_S | PSW_OV);
- if (overflow) PSW |= PSW_OV;
- if (quotient == 0) PSW |= PSW_Z;
- if (quotient < 0) PSW |= PSW_S;
+ if (quotient == 0) PSW |= PSW_Z;
+ if (quotient < 0) PSW |= PSW_S;
+ }
trace_output (OP_REG_REG_REG);
@@ -2340,19 +2401,20 @@ OP_28207E0 (void)
if (divide_by == 0)
{
- overflow = 1;
- divide_by = 1;
+ PSW |= PSW_OV;
}
+ else
+ {
+ State.regs[ OP[1] ] = quotient = divide_this / divide_by;
+ State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
- State.regs[ OP[1] ] = quotient = divide_this / divide_by;
- State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
-
- /* Set condition codes. */
- PSW &= ~(PSW_Z | PSW_S | PSW_OV);
+ /* Set condition codes. */
+ PSW &= ~(PSW_Z | PSW_S | PSW_OV);
- if (overflow) PSW |= PSW_OV;
- if (quotient == 0) PSW |= PSW_Z;
- if (quotient & 0x80000000) PSW |= PSW_S;
+ if (overflow) PSW |= PSW_OV;
+ if (quotient == 0) PSW |= PSW_Z;
+ if (quotient & 0x80000000) PSW |= PSW_S;
+ }
trace_output (OP_REG_REG_REG);
@@ -2373,24 +2435,31 @@ OP_28007E0 (void)
/* Compute the result. */
- divide_by = State.regs[ OP[0] ];
- divide_this = EXTEND16 (State.regs[ OP[1] ]);
+ divide_by = EXTEND16 (State.regs[ OP[0] ]);
+ divide_this = State.regs[ OP[1] ];
- if (divide_by == 0 || (divide_by == -1 && divide_this == (1 << 31)))
+ if (divide_by == 0)
+ {
+ PSW |= PSW_OV;
+ }
+ else if (divide_by == -1 && divide_this == (1 << 31))
{
- overflow = 1;
- divide_by = 1;
+ PSW &= ~PSW_Z;
+ PSW |= PSW_OV | PSW_S;
+ State.regs[ OP[1] ] = (1 << 31);
+ State.regs[ OP[2] >> 11 ] = 0;
}
+ else
+ {
+ State.regs[ OP[1] ] = quotient = divide_this / divide_by;
+ State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
- State.regs[ OP[1] ] = quotient = divide_this / divide_by;
- State.regs[ OP[2] >> 11 ] = remainder = divide_this % divide_by;
+ /* Set condition codes. */
+ PSW &= ~(PSW_Z | PSW_S | PSW_OV);
- /* Set condition codes. */
- PSW &= ~(PSW_Z | PSW_S | PSW_OV);
-
- if (overflow) PSW |= PSW_OV;
- if (quotient == 0) PSW |= PSW_Z;
- if (quotient < 0) PSW |= PSW_S;
+ if (quotient == 0) PSW |= PSW_Z;
+ if (quotient < 0) PSW |= PSW_S;
+ }
trace_output (OP_REG_REG_REG);