I've been attempting to port MAD to Windows CE running under ARM... it's tricky going, so far. I'm trying to convert the tons of macros that the FPM_ARM option uses to function calls, and having some limited success.
The biggest problem is that Embedded Visual C++, quite simply, does NOT support inline assembler. Ever. Despite what their own docs say. Another problem is that the macros aren't documented well; they don't explicitly state what kind of arguments they take or what they return.
Fortunately, EvC DOES support *external* assembly code; you can assemble an .asm file into an .obj file, turn it into a .lib then link it in with the rest of the C code. Even more fortunately, EvC is capable of converting C code to assembly code. This lets me write up a blank framework, compile it, and modify the resulting .asm file to do what I want.
So now I'm down to deciphering just exactly what each macro does to the arguments. It looks like mad_f_mul(x,y) takes two mad_fixed_t arguments and returns a mad_fixed_t value, that's simple enough; but it's unclear how the others are using their arguments.
Are the macro parameters for MAD_F_MLX, MAD_F_MLA, MAD_F_MLN, and mad_f_scale64 used ONLY as input parameters? 'cause if not, there's no way in heck to duplicate the full functionality of the macro in a function without operator overloading and hidden pointers; and MAD is a C project, not a C++ one.
On Thursday, June 19, 2003, at 01:55 PM, Tyler Montbriand wrote:
Are the macro parameters for MAD_F_MLX, MAD_F_MLA, MAD_F_MLN, and mad_f_scale64 used ONLY as input parameters? 'cause if not, there's no way in heck to duplicate the full functionality of the macro in a function without operator overloading and hidden pointers; and MAD is a C project, not a C++ one.
MAD_F_MLX, MAD_F_MLA, and MAD_F_MLN all modify their first two arguments. These arguments must be lvalues, so you could take their addresses to pass to a function.
On the other hand, you really only need to define an implementation for mad_f_mul; all the other macros have default implementations written in terms of this one.
mad_fixed_t mad_f_mul(x, y) x: (in) 32-bit fixed-point multiplicand y: (in) 32-bit fixed-point multiplicand returns: 32-bit fixed-point product (x*y shifted by MAD_F_SCALEBITS)
[Note that MAD_F_SCALEBITS may be redefined in synth.c, so if the implementation for mad_f_mul calls a function, MAD_F_SCALEBITS may have to be included as a function argument. You can avoid this by defining mad_f_scale64 to nothing and always scaling by MAD_F_FRACBITS.]
If you want more accuracy, you should define MAD_F_MLX instead and let the default implementations define everything in terms of this.
void MAD_F_MLX(hi, lo, x, y) hi: (out) 32-bit high word of 64-bit x*y product lo: (out) 32-bit low word of 64-bit x*y product x: (in) 32-bit integer multiplicand y: (in) 32-bit integer multiplicand
Defining implementations for any of the other macros is optional, if you have an efficient or particularly effective alternative to the default implementations.