I'm currently working on a fix for this.
The problem is that char values stored in registers occupy the upper byte, When multiplying two register-stored values, the result is in the upper word of the 32-bit result.
When multiplying memory-stored values, the char-to-int promotion occurs as expected, and the result is in the lower word of the 32-bit result. For extra fun, when multiplying register-stored and memory-stored values the result is stored in the middle two bytes of the 32-bit result.
It's difficult to control how values are stored, so currently char multiplication can give unexpected results (as has been shown already).
I'm working on a fix to force all char multiplications to be first converted to register-storage format, and to extract the correct portion of the result.
Here's the math behind this: Result = (A * 2^ * (B * 2^ = (A * B) * (2^16)
Before the operation completes, the resulting value needs to be converted to register-storage format, with the value stored in the upper byte of the result register.
Here's an example of what I'm trying to achieve:
mpy r1, r2 * Value A stored in register R1, value B in R2, result in [r2,r3]
* The resulting char value is stored in the low byte of R2
swpb r2 * Move result to high byte of R2 to convert to register-stored format
The problem I'm having is that I can't get the compiler to recognize that the the low word of the 32-bit result is clobbered by the multiply. This means that any value stored in R3 in the example above will be destroyed by the multiplication, but the compiler will assume it's still valid. That error value will propagate through the code and have unpredictable results.
I can't just promote all char values to int values either, The value we want will then be stored in the low byte of the 32-bit result, and we would still need to convert to register-stored format.
Bear with me, a fix should be coming soon...