Commit: MSP430: Fix bug in simulation of hardware multiplies
Commit Message
Hi Guys,
I am checking in the patch below to fix a bug in the simulation of
MSP430 hardware multiplies. The problem was that the result values
were not being distributed into all of the result variables, so it was
possible to perform a multiplication operation, switch to a new
multiplication mode and then fail to read back the result of the just
completed operation.
Cheers
Nick
sim/msp430/ChangeLog
2014-06-03 Nick Clifton <nickc@redhat.com>
* msp430-sim.c (get_op): Handle reads of low result register when
in MAC mode.
(put_op): Copy MAC result into result words.
Handle writes to the low result register.
@@ -413,16 +413,24 @@ get_op (SIM_DESC sd, MSP430_Opcode_Decoded *opc, int n)
switch (addr)
{
case 0x13A:
- rv = zero_ext (hwmult_result, 16);
+ switch (hwmult_type)
+ {
+ case UNSIGN_MAC_32:
+ case UNSIGN_32: rv = zero_ext (hwmult_result, 16); break;
+ case SIGN_MAC_32:
+ case SIGN_32: rv = sign_ext (hwmult_signed_result, 16); break;
+ }
break;
case 0x13C:
switch (hwmult_type)
{
+ case UNSIGN_MAC_32:
case UNSIGN_32:
rv = zero_ext (hwmult_result >> 16, 16);
break;
+ case SIGN_MAC_32:
case SIGN_32:
rv = sign_ext (hwmult_signed_result >> 16, 16);
break;
@@ -599,7 +607,8 @@ put_op (SIM_DESC sd, MSP430_Opcode_Decoded *opc, int n, int val)
case UNSIGN_MAC_32:
hwmult_accumulator += hwmult_op1 * hwmult_op2;
hwmult_signed_accumulator += hwmult_op1 * hwmult_op2;
- hwmult_result = hwmult_signed_result = 0;
+ hwmult_result = hwmult_accumulator;
+ hwmult_signed_result = hwmult_signed_accumulator;
break;
case SIGN_MAC_32:
@@ -607,11 +616,29 @@ put_op (SIM_DESC sd, MSP430_Opcode_Decoded *opc, int n, int val)
b = sign_ext (hwmult_op2, 16);
hwmult_accumulator += a * b;
hwmult_signed_accumulator += a * b;
- hwmult_result = hwmult_signed_result = 0;
+ hwmult_result = hwmult_accumulator;
+ hwmult_signed_result = hwmult_signed_accumulator;
break;
}
break;
+ case 0x13a:
+ /* Copy into LOW result... */
+ switch (hwmult_type)
+ {
+ case UNSIGN_MAC_32:
+ case UNSIGN_32:
+ hwmult_accumulator = hwmult_result = zero_ext (val, 16);
+ hwmult_signed_accumulator = sign_ext (val, 16);
+ break;
+ case SIGN_MAC_32:
+ case SIGN_32:
+ hwmult_signed_accumulator = hwmult_result = sign_ext (val, 16);
+ hwmult_accumulator = zero_ext (val, 16);
+ break;
+ }
+ break;
+
case 0x140: hw32mult_op1 = val; hw32mult_type = UNSIGN_64; break;
case 0x142: hw32mult_op1 = (hw32mult_op1 & 0xFFFF) | (val << 16); break;
case 0x144: hw32mult_op1 = val; hw32mult_type = SIGN_64; break;