This is the bug/patch tracker for Rockbox. Click here for more information.
Quick links: Bugs · Patches · Rockbox frontpage
FS#12120 - fix c implement of FRACMUL & FRACMUL_SHL
Attached to Project:
Rockbox
Opened by JoshuaChang (JoshuaChang) - Tuesday, 17 May 2011, 08:53 GMT+2
Last edited by Nils Wallménius (nls) - Thursday, 30 June 2011, 10:33 GMT+2
Opened by JoshuaChang (JoshuaChang) - Tuesday, 17 May 2011, 08:53 GMT+2
Last edited by Nils Wallménius (nls) - Thursday, 30 June 2011, 10:33 GMT+2
|
Detailsthis is a small patch to fix the c language implement of FRACMUL & FRACMUL_SHL
the original ones dealing the immediate int32 negative value as int64 positive value. |
This task depends upon
Closed by Nils Wallménius (nls)
Thursday, 30 June 2011, 10:33 GMT+2
Reason for closing: Fixed
Additional comments about closing: fix comitted
Thursday, 30 June 2011, 10:33 GMT+2
Reason for closing: Fixed
Additional comments about closing: fix comitted
You changed the macros to truncate the multiplicands before doing the multiply which will just lose precision.
FRACMUL((int32_t)0x80000000, aaa)
or
int32_t x = 0x80000000;
FRACMUL(x, aaa)
should work fine but indeed your patch fixes this, i'm just unsure if it's the right way or if your code using the macro shoul ensure the correct type.
NVM: C99 6.4.4.1 says if it doesn't fit an signed int, it'll be extended to unsigned int (for hex-numbers).
In this case, the code shouldn't make it signed (especially not long, since that doesn't fi). We need to deal with the fact that 0x80000000 is unsigned, or just write INT_MIN instead.
as described in the file itself, it should tread all the input operand as int32 by default, not int64, we use (long long) to convert the operand because we need to make the ”*“ return the 64bit value
Your problem is still that you are giving it an *unsigned * value and it's just a question of which code is responsible for the type being correct, btw casting to long is wrong anyway since long == long long on lp64 platforms like linux on amd64
FRACMUL(x, y) ((int32_t)((int64_t)(int32_t)(x) * (int32_t)(y) >> 31))
I think I prefer inline functions too.
#ifdef SIMULATOR
int32_t FRACMUL(int32_t x, int32_t y) {
#else
inline int32_t FRACMUL(int32_t x, int32_t y) {
#endif
edit: there's a typo, in32_t instead of int32_t also, doesn't work for coldfire because of an intermediate constraint on the z param...
Edit: Only the spc codec uses this during fading. So, no impact on codecs.
apps/fracmul.h: In function `dsp_set_crossfeed_cross_params':
apps/fracmul.h:79: warning: asm operand 4 probably doesn't match constraints
apps/fracmul.h:79: warning: asm operand 5 probably doesn't match constraints
apps/fracmul.h:79: warning: asm operand 4 probably doesn't match constraints
apps/fracmul.h:79: warning: asm operand 5 probably doesn't match constraints
apps/fracmul.h:79: error: impossible constraint in `asm'
apps/fracmul.h:79: error: impossible constraint in `asm'
apps/fracmul.h:78: warning: 't' might be used uninitialized in this function
apps/fracmul.h:78: warning: 't' might be used uninitialized in this function
According to betrik, the same is true for the "zipit Z2".
Reverting to the old macro makes it compile again.
FRACTMUL() compiles fine, FRACTMUL_SHL() doesn't.
Any idea what migth be going on?
Edit: gcc version: sbox-arm-linux-gcc (GCC) 3.4.4 (release) (CodeSourcery ARM 2005q3-2)